In the previous post I described what I call “Assembly Java”. The name itself, Assembly Java, is paradoxical (oxymoronic) through the opposition between a high-level programming language (Java) and a low-level programming style (‘assembly language’).
The previous post was intended, I guess, as a (subtle) critique of Java used as a low-level programming language.
In the constrained mobile (MIDP) environment, the Java language becomes deprived (through the low-level programming style) of its advanced features, such as classes, virtual dispatch, polymorphism, packages, reflections, and, to some degree, garbage collection. Java turns into a C-like low level language, while still missing some of the C features that would have been useful in the restricted environment, such as: data structs, stack-allocated instances (‘auto’ variables, object instances that aren’t allocated on the heap), arrays of structs (with the structs stored inside the array, not with pointers stored in the array), inlined functions, preprocessor (used for conditional compilation and macro expansion), enums (useful for the ’switch-dispatch’ pattern, among other things), first-class functions (‘function pointers’), etc.
But don’t get my critique too harsh: I’m an enthusiast mobile Java developer myself, and I would recommend Java as the first choice (by far) for mobile application development.
There is also the time aspect: due to the quick evolution of the hardware, the mobile environment is becoming less and less constrained, and thus mobile Java programming is gradually getting closer to the standard Java programming, employing less low-level optimizations and more high-level design. Also the mobile VM (java virtual machine) should be expected to become smarter in time and, why not, perhaps the java compiler (javac) might employ some compile-time optimizations (such as method inlining, and a bunch of expression and loop optimizations) as well.
In the meanwhile, a smart obfuscator such as Proguard can help with the size-reduction of the compiled classes (through automatic class and method renaming, package renaming and elimination, class-merging, method inlining), thus allowing you to keep your design/code simple, clear and clean, while still taking advantage of these optimizations. (note: class-merging is still experimental in proguard, and method inlining is planned for the future).
For the developer, the first concern should be to (quickly) implement the application and get it to work correctly, and only afterwards does the performance (and optimizations) come into discussion. This is simply because the performance of an unfinished or failed project is of little importance.
Getting the application done is no easy task. You should take advantage of clean design, simple code, clear and small interfaces, hidden (private) implementations, because all these help you to develop your application, to modify and adapt it, and to reuse your code.
You should strieve to achive beautiful code, kind of an art-work. A measure for this is to imagine that your code is open-source, and all your friends look at it and discuss it. If you’d still be proud of your code were it public, it’s a good sign.
The so-called guidelines from my previous post are rather bad advice, and were intended for your entertainment (note that #0-#10 is in fact 11 items, not 10 as stated in the post). By negating (complementing?) them you might get some sound design advice.
Let’s try the negation trick:
#0. Don’t merge classes.
You should not merge un-related functionality together in a single class. You should keep the class design clear and neat because it makes the code easier to understand, to modify, and to reuse between projects. As classes do incur some space overhead, you should avoid the extreme of class inflation, the situation where you have a large number of very small classes (classes with just one or two methods inside). Perhaps a reasonable number of classes might be somewhere between 4 and 20 classes, depending on project size and design complexity.
Proguard the obfuscator offers an experimental merge-class feature. This is another reason to keep your design/code clean, with nice classes, and you can always get the merged-class benefit at the obfuscation step if you want it, with no negative impact on your class design.
#1. Don’t merge methods.
The space overhead of a function declaration is so small, that you shouldn’t worry about it. Do split big methods if it increases the clarity of the code. Strive for having each method do just one thing. Try to have methods with small and clear signatures (small number of parameters) and clear semantic (‘what does this method do?’).
#2. Switch or polymorphic dispatch?
Using the switch() instead of the polymorphic dispatch is generally considered bad OOP practice. You may nevertheless want to do it sometimes to avoid having a large number of small classes. Ponder well when choosing between the two.
#3. Instantiation vs. reuse
While object instantiation economy is not bad, don’t sacrifice too much of your design quality for the sake of it, because at the same time object instantiation / garbage collection is not prohibitively expensive when done with measure. The places where you should keep an eye on object instantiation is inside tight loops (e.g. inside a for loop, it may be a bad idea to repeatedly instantiate / garbage collect a temporary object — you may want to instantiate it just once outside the loop, and reuse it during the loop).
I’ll stop here, saving you the remaining ‘guidelines’.
6 Comments
Nice posts on JavaME.
Can you give a reference to an open source project that achieves balance between Assembly Java and sound OO principles?
I’ve just taken a look at your Menstral project – is its source available ?
Menstral’s source is not available right now, but I’m considering whether to open-source it, mainly I try to evaluate if the benefit (of open-sourcing it) would out-weight the cost/risk.
Until now I’ve received very few inquiries about Menstral as open source (yours is only the second). It seems that the typical Menstral user is not technical, and so he doesn’t care too much about the source.
I am new to mobile programming I have an error says srting index out of bounds
Index out of bound mean that you are trying to access array out of bound. For example you have an array int a[10] and you are trying to access a[15].
In case you were wondering, complementation is for sets. If A is a set, then Ac (with the c subscripted) is the set of everything _not_ in A.