08-24-2010 01:02 PM - edited 08-24-2010 03:40 PM
Hi all!
I have a project that have to support multiple API of the BB OS.
I investigated a bit how it should be designed and want to summarize.
Hope someone will find this useful.
I wrote a short list of principles with examples to show in future to my
co-workers. But first, I would like to hear some feedback from knowledgeable
people. Please kindly disregard my poor english
.
So please point me if I'm mistaken somewhere or if I skipped something,
or maybe some places should be clarified.
1. Separate API-dependent code from API-independent. API-independent code
should call API-dependent one via fixed interface. Instances of the objects
that implements API-specific logic should be created using 'abstract factory'
pattern:
Here is example of abstract factory implementation:
abstract class AbstractFactory {
static public AbstractFactory getInstance() {
// #ifdef BB42
return new ClassFactory42();
// #endif
// #ifdef BB43
return new ClassFactory43();
// #endif
...
}
abstract public AddressBookManager getAddressBookManager();
abstract public NetworkManager getNetworkManager();
abstract public DataStore getDataStore();
}
abstract class AddressBookManager {
...
}
abstract class NetworkManager {
...
}
abstract class DataStore {
...
}
Here are directives BB42, BB43... specify target API version.
2. Include in build all API-specific implementations that uses API lower or equal to current API version. This rule will allow to prevent code duplication by using class inheritance. For example we have to support BB OS 4.2 and 4.3, so it's better to inherit 4.3 implementation from 4.2 one and just to overload those methods that really changed:
class ClassFactory42 extends AbstractFactory {
public AdressBookManager getAdressBookManager() {
return new AdressBookManager42();
}
public NetworkManager getNetworkManager() {
return new NetworkManager42();
}
public DataStore getDataStore() {
return new DataStore42();
}
}
class ClassFactory43 extends ClassFactory42 {
public NetworkManager getNetworkManager() {
return new NetworkManager43();
}
// other implementations didn't change
}
////////////////////
class NetworkManager42 extends NetworkManager {
HttpResponse processRequest(Request request) {
...
}
boolean isNetworkAvailable() {
...
}
private char[] readResponse() {
...
}
}
class NetworkManager43 extends NetworkManager42 {
boolean isNetworkAvailable() {
...
}
// other methods didn't change
}
3. Exclude from build implementations that uses API version which is greater than target API version. Implementations that uses API greater than target one will rather compile with error (smth like "class not found"). So we need to remove them from build using preprocessor directives. At the same time we have to provide p. 2.
Let's assume that target OS version is 4.5. We should include in build implementations that uses API versions 4.2, 4.3, 4.5 and exclude API 4.6+.
RAPC preprocessor allows to use just simpliest directives #ifdef <DIRECTIVE>, #ifndef <DIRECTIVE>, #else, #endif. So including/excluding of API-specific implementations can be provided via additional directives. (Note: if you use third-party preprocessor that can calculate expressions, there is a simplier solution, something like this:
// #if CURRENT_VERSION >= 4.5
class ClassFactory45 {
...
}
// #endif
).
Lets specify directives that reflects minimal API version needed to build code enclosed with these directives. For example, for code that uses API 4.2 there will be MINIMAL_API_42 directive, for code using API 4.5 there will be MINIMAL_API_45 directive. So for target OS 4.5 the next directives should be specified:
BB45: MIN_BB42, MIN_BB43, MIN_BB45.
These directives should be used in the following manner:
NetworkManager42.java
//#preprocessor
//#ifdef MIN_BB42
class NetworkManager42 extends NetworkManager {
...
}
//#endif
NetworkManager43.java
//#preprocessor
//#ifdef MIN_BB43
class NetworkManager43 extends NetworkManager42 {
...
}
//#endif
NetworkManager47.java
//#preprocessor
//#ifdef MIN_BB47
class NetworkManager47 extends NetworkManager43 {
...
}
//#endif
In the previous example API 4.7 will be excluded from compilation. But other implementations will be included. Here are some more examples of additional directives:
TatgetAPI=4.2 : specify MIN_BB42
TatgetAPI=4.3 : MIN_BB42, MIN_BB43
TargetAPI=4.5: MIN_BB42, MIN_BB43, MIN_BB45
TargetAPI=4.6: MIN_BB42, MIN_BB43, MIN_BB45, MIN_BB46
...
Thanks in advance.
Nikolay.
08-24-2010 03:42 PM
something wrong with the image. Here is link to image hosting using of abstract factory image
10-25-2011 09:03 AM
I am tring to use the
// #if CURRENT_VERSION >= 4.5
but the compiler is compiler is trowingth exeption
#endif' without '#ifdef
I have taken note of "(Note: if you use third-party preprocessor that can calculate expressions"
how do i get the third-party preprocessor that can calculate expressions ?
10-25-2011 09:37 AM
Give this a quick read:
http://supportforums.blackberry.com/t5/Java-Develo