Tuesday, March 24, 2015

Mindful selection of constant values (for uniqueness)

(I ran into this issue when trying to grok the Android Bluetooth API, and thought it was worthy of a post.)

Say you have a value and need to know the name of the constant. For example, you are debugging some code, and things would be much more obvious if you could log the name of a state returned by a method getState(), not just its value:

1
2
3
4
5
6
7
8
  // Possible device states
  public static final int STATE_IDLE = 0x00;
  public static final int STATE_STARTING = 0x01;
  public static final int STATE_RUNNING = 0x02;
  ...
  public int getState() {
    return mState;
  }

You could solve this with a lookup table. But if there are many constants, or the documentation is in the code, or new constants may be added later, or there are undocumented manufacturer additions, you can save a lot of code by using reflection to look up the names of the constants at runtime.

With reflection, you would obtain all the constants in the class, look for the constant whose value matches the one you got from getState(), and display the constant's name instead of its value.

But say that this code is also in the same class:

1
2
3
4
5
6
7
  // Possible power settings
  public static final int POWER_OFF = 0x00;
  public static final int POWER_ON = 0x01;
  ...
  public int getPower() {
    return mPower;
  }

While it may make sense to represent power settings with a 0 and 1, the reuse of these values breaks our ability to uniquely discover a constant's name using reflection, because one value now maps to two constants.

One approach to ensure uniqueness is to use a higher order byte to encode the information that the constant represents. In this example, hex 0x0a00 is added to STATE_ constants, and 0x0b00 is added to POWER_ constants:

1
2
3
4
5
6
  public final static int STATE_IDLE     = 0x0a00;
  public final static int STATE_STARTING = 0x0a01;
  public final static int STATE_RUNNING  = 0x0a02;

  public final static int DEVICE_OFF     = 0x0b00;
  public final static int DEVICE_ON      = 0x0b01;

Developers may not encounter the need for reflection in normal coding. But it can come in very handy during testing, or when you encounter a complex system like Bluetooth, and are trying to figure it out. There are going to be times where different constants must have the same value. But many times, values can be unique. Mindful consideration of constant values to permit discovery of their corresponding constant names through reflection may be appreciated by others who will eventually be interacting with your code.

1 comment:

  1. Being a blogger,I always think of making something which could help us in forming android studio code formatter and you have just made my life so easy!!

    ReplyDelete