Dear reader of Juri's TechBlog,
I moved my blog to a new domain and a new hosting solution as well. I'm now blogging on juristr.com.

Best practices: The challenge of designing software for wireless devices

Designing good software for wireless devices such as mobile phones is not straightforward. Developers have to consider and address the device's constraints such as memory, processing power, input, screen etc.. but also the environment such as wireless network constraints.

I found an interesting sun article that gives some suggestions on wireless software design. For instance it suggests to pose the following questions when developing wireless applications:

  • What impact do devices with limited resources have on application design?
  • How important is it to develop applications that are platform-independent?
  • What security issues should I be aware of?
Moreover the article provides some guidelines which I find quite useful to take a look at:
  • Environment. Do some research up front. You must first understand the needs of your potential users and the requirements imposed by all networks and systems your application will rely on.
  • Architecture. The architecture of your application is very important. No optimization techniques will make up for an ill-considered architecture. Your two most important design goals should be to minimize the amount of data transmitted over the wireless link, and to anticipate errors and handle them intelligently.
  • Application partitioning. You need to think carefully when deciding which operations should be performed on the server and which on the wireless device. MIDlets allow you to locate much of an application's functionality on the device; it can retrieve data from the server efficiently, then perform calculations and display information locally. This approach can dramatically reduce costly interaction over the wireless link, but it is feasible only if the device can handle the processing your application needs to perform.
  • Data representation. Data can be represented in many forms, some more compact than others. You should consider available representations and select the one that requires fewer bits to be transmitted. For example, numbers will usually be much more compact if transmitted in binary forms rather than string representations.
  • Message latency. In some applications, it may be possible to do other work while a message is being processed. If the delay is appreciable -- and especially if the information is likely to go stale -- it is important to keep the user informed of progress. Design the user interface of your applications to handle message latency appropriately.
  • Interface simplicity. Keep the application's interface simple enough that the user seldom needs to refer to a user manual to perform a task:


    1. Reduce the amount of information displayed on the device.
    2. Make input sequences concise so the user can accomplish tasks with the minimum number of button clicks.
    3. Offer the user selection lists.
These guidelines follows a section called "performance-driven programming", giving the following suggestions:
  • Do not initialize objects to null.
    That chore is handled automatically
  • Wherever possible, use local variables instead of class members.
    Access is quicker.
  • Minimize method calls...
    The Java Virtual Machine (JVM) loads and stores a stack frame every time it calls a method. For example, instead of doing something like this...


    for(int i=0; i< obj.length; i++) {
        // do something with array elements
    }
    
    ...where the length of the array is evaluated every time the loop iterates, it is more efficient to define a local variable and call the accessor only once:


    int len = obj.length;
    for(int i=0; i<len; i++) {
        // do something with array elements
    }
  • Minimize object creation
    Object creation leads to object destruction and reduces performance. Instead, design objects that can be recycled. Instead of creating return objects inside of methods, consider passing a reference to the return object and modifying its values. For example, this code snippet...


    int len = record.length;
    try {
        for(int i=0; i<len; i++) {
     MyObject obj = new MyObject();
     // do something with obj
        }
    } catch(Exception e) {
        e.printStackTrace();
    }
    
    ... creates and destroys a new instance of MyObject every time the loop iterates. You can avoid this object churning -- continually creating and discarding objects in the memory heap -- by moving the object creation outside the loop. A more efficient way to rewrite the code above would be to create the object outside the try statement and reuse that object as follows:


    int len = record.length;
    MyObject obj = new MyObject();
    try {
        for(int i=0; i<len; i++) {
     // do something with obj
        }
    } catch(Exception e) {
       e.printStackTrace();
    }
    By reusing a single object instead of creating many the program uses
    less memory and the processor doesn't spend as much time collecting
    garbage.
  • Avoid string concatenation.
    Concatenating objects with the + operator causes object creation and subsequent garbage collection, and thus chews up both memory and processor time. It is more efficient to use StringBuffer.
  • Avoid synchronization.
    If a method takes longer than a fraction of a second to run, consider placing the call to it in a separate thread.
I think the only point which may be a bit unclear (at least to me) is the suggestion that says to "whenever possible, use local variables instead of class members". Attention, this doesn't mean that you should directly access class fields (class member variables) as often misunderstood. The usual encapsulation rule from object oriented programming still holds. Well ok, accessing them directly may speed up your app even more since you don't have an additional method call (see 3rd point above), but I highly discourage that practice!!
What is intended with this suggestion is more that you should prefer using local variables (defined in a block) rather than continuously accessing the object's members. For instance if you have to use the name of a class Person multiple times within a block, you better retrieve it once, store it in a local variable and then use that instead of repeatedly invoking personObj.getName().

Parts of this post have been taken from: http://developers.sun.com/mobility/midp/articles/uidesign/

Posts you might also be interested in..

Credits: Hoctro | Jack Book

2 Comments:

masc said...

Hi, a very good article ... and now I can rewriting my application "Fita2ME" ;-)

Juri Strumpflohner said...

Hi,

come on :) it won't be soo bad ;)

But indeed, on a first look, developing wireless applications for J2ME seems to be just the same as for a normal desktop environment beside some differences in the available Java libraries. But once you come into the stage where you test your application on DIFFERENT mobile phones you'll soon discover problems in reaction time, memory, not working functionalities on some phones while on others they work etc...
Then, the challenge begins :)

Post a Comment