Az előző kitérő után most térjünk vissza egy kis kocka témához. A minap érdekes felfedezést tettem, miközben véletlenül a GEF belső kódjába tévedtem debug közben. Alapvetően egyébként meg vagyok elégedve a GEF és általában az eclipse platform minőségével, ritka az az eset, hogy a fejemet fogom egy-egy megoldás láttán.
A következő kódrészlet ugyan működik és mivel a publikus api elrejti, az átlag fejlesztő nem találkozik vele, mégis érdemes rávetni egy pillantást. További szócséplés helyett következzék a kód, szerintem magáért beszél:
//AbstractEditPart.class
private Object[] policies;
//...
/**
* @see EditPart#installEditPolicy(Object, EditPolicy)
*/
public void installEditPolicy(Object key, EditPolicy editPolicy) {
Assert.isNotNull(key, "Edit Policies must be installed with keys");//$NON-NLS-1$
if (policies == null) {
policies = new Object[2];
policies[0] = key;
policies[1] = editPolicy;
} else {
int index = 0;
while (index < policies.length && !key.equals(policies[index]))
index += 2;
if (index < policies.length) {
index++;
EditPolicy old = (EditPolicy)policies[index];
if (old != null && isActive())
old.deactivate();
policies[index] = editPolicy;
} else {
Object newPolicies[] = new Object[policies.length + 2];
System.arraycopy(policies, 0, newPolicies, 0, policies.length);
policies = newPolicies;
policies[index] = key;
policies[index + 1] = editPolicy;
}
}
if (editPolicy != null) {
editPolicy.setHost(this);
if (isActive())
editPolicy.activate();
}
}
Akinek nem világos elsőre, kifejteném a problémát: láthatóan egy tömböt használ a java-ban alapértelmezésként elérhető "Map" funkcionalitásának a kiváltására. A tömb páros (és nulladik) helyén szereplő elem tárolja a kulcsot, az utána lévő páratlan helyen lévő elem az érték.
Minden elem hozzáadásakor dinamikusan növeli a tömb méretét, törléskor meg egyszerűen null-ra állítja a tömb megfelelő elemét. Ehhez még társul egy custom iterátor is, ami a tömb nem null elemeit listázza.
Őszintén nem értem a tervezési döntést, ami a tömb-alapú Map-hez vezethetett. A memóriaigénye a HashMap-nek nem sokkal több, és mivel jellemzően kis elemszámú esetek fordulnak elő, ez nem számottevő. A sebessége a HashMap-nek jobb, a "get" és "put" metódusok általános esetben konstans, de mindenképpen kevesebb a tömb végigjárásánál. Mindennek a tetejébe a fenti kód Map alkalmazásával kb. 3 sorra cserélhető, nem beszélve az osztály egyéb kódjáról, ami a tömböt piszkálja.
Egyetlen érthető mentségként csak arra tudok gondolni, hogy esetleg a kód korábban íródott, minthogy a java collections API-ba belekerült volna a Map. Ez viszont az 1.2-es verzióban történt meg, tehát elég régen. Nem tudom mennyi idős a GEF, így ezt nem tudom eldönetni.. Mindenesetre ez a kód nálam megütötte a WTF szintet.
Nagyon gonosz kérdés, amit Eclipse-környéki hasonló bugbejegyzéseknél fel szoktak tenni: bugreport? 😀
Ehhez még akár patchet is tudnál villámgyorsan küldeni.
A GEF biztos, hogy sokkal újabb, mint a Java 1.2 egyébként, szal olyan fejlesztő készíthette, aki nem ismerte a Map típust, utána pedig nem volt senki, aki a működő kódhoz hozzányúlt volna…
Jogos. Alkalomadtán meg is fogom tenni. A post rejtett célja az volt, h más is ránézzen a kódra és esetleg felhívja a figyelmemet egy olyan részletre, ami indokolná a választott megoldást.