Improving Code Efficiency and Clarity
Up to now, we were happy just to get things to work, so called prototyping. Now we need to look over the code and try to improve the code looking for redundant code, ways to improve efficiency or just ways to improve the clarity of the code. In fact, we may favor more verbose code and variable names if it improves clarity. The Eclipse IDE provides refactoring tools that will automagically propagate changes to say, variable names, to the entire class. So the cycle is:
Write unit requirements
Prototype code that meets unit requirements
Refactor code
Test the refactored code to ensure that it still meets unit requirements
Extracting Strings
The first step is to be sure that we have removed all of the string values from main.xml and moved them to strings.xml. This makes the code in the project easier to maintain and supports localization. See the Android docs on resources. It may be possible to use the refactor tool as: Refactor --> Android --> Extract Android String.
Minimize Number of Larger Objects
The most obvious need for efficiency is to move the cipher creation code to the class constructor. This way the cipher is only instantiated once. So the new constructor looks like this in Model.java:
private Cipher cph= null;
public Model() {
try {
cph=Cipher.getInstance("DES");
}
catch (NoSuchPaddingException e){} //cph == null
catch (NoSuchAlgorithmException e){} //cph == null
}
We need to check for a null cipher (cph) in the tryEncrypt and tryDecrypt methods.
if (cph == null){throw new Exception("Cannot create cipher.");}
Plug In Architecture
A major refactoring would involve implementing a plug in architecture for different encryption algorithms. So given an interface:
/*
* IModelSpec
* Interface for Decryption Specifications for encrypt/decrypt engine
* JALComputing Copyright 2011
*/
public interface IModelSpec {
String getModelName();
String getFullModelName();
int getIvLength();
int getKeyLength();
String getDefaultKey();
boolean getIsHashPassword();
}
You could then write classes that implement this interface such as DESModelSpec, TDESModelSpec and AESModelSpec. You could then change the encryption algorithm with one line of code as in:
private Model model= new Model(new DESModelSpec()); // 56 bit key Single DES with IV
private Model model= new Model(new AESModelSpec()); // 256 bit key AES with IV
private Model model= new Model(new TDESModelSpec()); // 168 bit key Triple DES with IV
Consolidating Repeated Code Segments
If you note code segments that seem to repeat in your project, consider consolidating that call into a method, passing appropriate arguments. This strategy can pay big dividends in the future when you change design requirements. Instead of changing code throughout the project, you can simply rewrite the common method.
Renaming Variables
You can quickly rename variables in a class by selecting the text and choosing Refactor --> Rename. Enter the new name and hit return. All of the variables in the class are renamed automagically. Cool!
Using Parcels
Passing objects between Activities is great for development. Once the state interface has stabilized, consider refactoring the code to use Parcels if needed for speed. Note that parcels do not support flattening of methods. At least one author suggest that Parcels are not meant to be passed to an activity.
JAL