tags:

views:

515

answers:

4

On a project targeting as many feature phones as possible (Nokia 3110 Classic, Samsung E250, Motorola SLVR L7, etc.), how should it be designed at a high level in terms of code structure? I don't mean in terms of per-handset support, as we are using Polish for that.

I'm an experienced C# developer moving on to J2ME development within my company. Several months ago, management hired in a senior J2ME developer, as the existing developers lacked any J2ME experience. I'm now joining that team with another C# developer, and we both have some reservations at what we're seeing. While the software runs and meets business's requirements, the design of the app seems entirely wrong to me.

Rather than using OO, most of code is composed of static methods and constants, and is in as few classes as possible (15, far as I can tell), because of "memory constraints on the handsets". Some of these are thousands of lines long. Apparently, none of the built-in UI elements are used with the exception of Canvas, as they "do not provide enough control".

All the forms/windows/pages (Not sure of the correct term) have a static method in one class, in which we have code to set up the UI of that form/window/page. It is as follows:

UiElement items[] = new UiElement[8 + (fieldCount * 4)];
int y = 0;
items[y++] = new UiElement("name", UiElement.TYPE_TEXT_FIELD, "Name", TextField.ANY, true, "", true, null, -1, 0);
items[y++] = new UiElement("address", UiElement.TYPE_TEXT_FIELD, "Mobile", TextField.PHONENUMBER, true, "", true, null, -1, 0);
// ...
items[y++] = UiElement.LINE;
items[y++] = new UiElement("button", UiElement.TYPE_BUTTON, "Save", -1, false, "", true, null, UiElement.TYPE_LINK, ActionHandler.LINK_UPDATE_USER);
items[y++] = new UiElement("", UiElement.TYPE_RED_BUTTON, "Delete user", -1, false, "", true, null, UiElement.TYPE_LINK, ActionHandler.LINK_DELETE_USER);
items[y++] = UiElement.LINE;
items[y++] = new UiElement("", UiElement.TYPE_LINK_ARROWS, "Back to choose category", 0, false, "", true, null, -1, ActionHandler.LINK_MC_SELECT_CATEGORY);
items[y++] = UiElement.LINE;

The main constructor for UiElement is

public UiElement(String RMSref, int inputType, String displayText, int additionalInputType, boolean mandatory, String aditional, boolean selectable, Image img, int displayType, int actionLink)

At the end of this, a call is made to save the items array on a class that extends Canvas. That class has a paint method with a huge switch block, branching on UiElement's inputType. From there, it goes to a static method on the "graphics" class, which has methods for each different kind of "control" to handle that "control"'s painting.

Effectively, it seems like everything is procedural when it can be, and only uses OO when it has to. I've asked the senior dev why we don't have a base Control class, and then subclasses of that, each with self-contained painting, properties, etc., instead of this generic UiElement class, and it's apparently because lots of classes use up too much memory. I've also been told that some phones have buggy Java runtimes, so that they don't free memory correctly. This is also the reason there is only a single Canvas.

As another example, all the text output is done through the use of bitmap fonts, rather than using the handset's internal font rendering. We've been told that it's to provide uniform rendering across handsets, rather than relying on their internal fontsets and sizes.

Is this the right way to do it? Are the things we've been told correct? I'm hoping to try avoid this turning into a submission to TheDailyWTF. Thanks.

+2  A: 

In J2ME Development We cannot have OOP Principles going, the best way is to keep everything in single class even without having any packages for the optimum memory usage. But in programing perspective we go for some level of OO Concepts like separating code into useful set of classes and packages. But its better you do not go for that Sub classing concepts. J2ME Polish is really useful when developing J2ME Applications specially a generic one. IMO you are going in right path, we can't have all OOP applied when developing J2ME apps due to limited heap size, specially when going for a generic J2ME Application concerning large number of handset devices.

Tharindu Madushanka
+5  A: 

Hi,

welcome to the world of j2me.

Things have gotten better a bit over the times. But what you are seeing is in fact the way todo things on the oldest of phones (especially Nokia series 40 (generation 1)) and ancient samsungs. It's a fact that any class added will make your jar size go up. And since some phones impose a limit of 64kb, any byte counts.

If these old phones are not targetted anymore, you can let go of this ancient practice and go more the OO way.

The bitmap fonts is true also. On every phone brand (even different models from the same brand) the phones own font sizes vary enormously. On a Motorola if one asks for a small font, one gets a huge font. Better yet, any font requested on the motorola is huge and unworkable.

The pros and cons of phone fonts: - Phone fonts don't cost precious jar memory. Bitmap fonts are costly - Bitmap fonts look the same on any phone - Phone fonts can be drawn in any color (bitmap fonts have to be included double if you want to have them in 2 colors). - The latest Nokia phones actually draw the phone fonts anti aliased giving very nice results. Bitmp fonts will never be antialiased unless it's already done in the bitmap, which means you can only use them on one background color (The one antialiased too).

Anyhow, it sounds like you've got a developer there with a lot of experience (baggage?) of j2me coding. Maybe a bit too much. If there's no need to target ancient phones, then clean up the code and make it more modern.

Toad
Bitmap Font could be palettized, thus you can save Jar space. Even the not so old Blackberry 8320 has a lot of issues while having large number of classes. If you read their developer documentation, u will find stuffs like "Don't use interfaces"
Azlam
azlam: they can, but that means you have to change the palette at the moment of instantiating the image, and basically have 2 uncompressed copies in memory at the same time. So if runtime memory is limited this approach has its share of problems too
Toad
+1  A: 

My £0.02 worth:

The built-in UI components (LCDUI) are generally hideous. They can be useful if you want your app to look like a "handset native" app; however you have very little control over their appearance. What looks pretty on one handset will look awful and out of place on another. It's very very difficult to write cross-handset friendly code using LCDUI and I'd avoid like the plague.

Rolling your own canvas-based components means you have far greater control over their appearance and behaviour across handsets.

Regarding fonts, I personally don't like to bother with bitmap fonts. They are slow, heavyweight, cumbersome, and can be difficult to get looking right as you need to implement your own kerning etc, plus what of internationalisation? True, some handset fonts are abominable (old Motos in particular as reinier mentioned). However, do remember that the user will be used to them on that handset, and careful UI design (and component implementation) means you can work around any size font (note that the reason the old Motos give you a large if you ask for small, is that they actually have only one font).

There are many, many obscure handset bugs you'll need to work around, depending on what your app does. Yes some handsets have quirks on GC/memory allocation that can bite you.

However, only if you're targetting proper ancient/low memory handsets should you need to go to the full "put everything in one single class/method" extreme. Any effort you put in this department will be moot when compared to the overhead of bitmap fonts IMO.

HTH

funkybro
A: 

I second reiner's post here. I do want to add that string embedded in code are a maintenance nightmare, better to have them in something like CustomStrings class as constants. Same with image/assets names, its just easier to maintain.

Another point I want to make is for initial launch aim for high end (greater than 64k limit jar size) handsets. Its much painless this way. Later on you can add support for low end handset.

Also that senior J2ME engineer seems to know his way around, listen to him about the inherent issues with J2ME development, not necessarily for the solutions.

omermuhammed