Thursday, April 10, 2008

Internal Refactoring

For my 10-day visit to Tokyo, Kyoto, Nara, Hakone and Chiba (my brother-in-law's wedding), I needed to refactor my internal progamming a bit to avoid OutOfMemoryExceptions.

// This class is package protected to avoid
// external programs messing up.
class Brain {

public void handleEvent(MeetNewPersonEvent event) {
...
if (getLocation().equals(Locations.JAPAN)) {
fireEvent(new BowEvent(event));
}
}

public void handleEvent(BowEvent event) {
// Avoid infinite loop. The problem is the
// 'esteemed higher' part, the person
// for whom you're bowing may think the same.
if (event.isPersonEsteemedHigher()
&& !event.hasBowedTooMuch()) {
bow();
} else {
nod();
}
}

protected void bow() {
lookSincere();
smile();
bendForward();
}


I also needed to reprogram the eating subroutines.

public void handleEvent(FeelingHungryEvent event) {
...
if (getLocation().equals(Locations.JAPAN)) {
// This was a tricky one to handle,
// the implementation is left
// as an exercise to the reader.
uploadChopsticksRoutine();
}
}


The RunForTrainEvent and especially the WaitForTrainEvent could be canceled out since public transportation is much better than the location I originally wrote it for (Belgium).

public void handleEvent(RunForTrainEvent event) {
if (getLocation().equals(Locations.JAPAN)) {
stopRunning();
relax();
Thread.sleep(5*Timer.MINUTE);
}
}


Finally, I needed to handle the RunningNoseEvent (extends HasColdEvent) better.

public void handleEvent(RunningNoseEvent event) {
...
if (getLocation().equals(Locations.JAPAN)) {
// Blowing your nose in public is NOT DONE
// in Japan. This is considered
// a bit the same as burping.
// Public humiliation is your part when
// this is not checked.
dipNose();
} else {
blowNose();
}
}

protected Location getLocation() {
...
if (isCurrentLocationUnknown()) {
if (bodyTallerThanMostOthers()
&& friendlyPeople() && metroEvery2Minutes()
&& dressCode.equals(Dresscodes.COSTUME)
&& eatingCode.equals(EatingCodes.SHOPSTICKS)) {
return Locations.JAPAN;
}
}
}

} // End class


This is released under an Apache license. Please notify me if these changes are of any use to you.

Labels:

Monday, June 18, 2007

www.koopjeszoeker.com

After tryouts with script.aculo.us, mootools and DWR, I finally decided to go with Google Web Toolkit (GWT) for the (badly needed) update of my koopjeszoeker website.

GWT allows me to make changes much faster than I could do it with DWR or other frameworks. Writing javascript from Java code seems strange at first, but it's much like writing a Swing application.

On top of that, I get the following benefits:

  • I don't need to worry about versioning, GWT uses hashes which create new filenames for every release. So I can cache all files "until the sun explodes".

  • GWT compresses and obfuscates the generated javascript

  • Internationalisation is fully supported as in Java with properties files

  • GWT creates separate files for every browser and language, which means that a Dutch user on Firefox doesn't need to download code that can be used on an English Safari.

  • The javascript is compatible on all major browsers



My experiences:

  • During development, compile to Firefox for one language instead of to all browsers for all languages. You can do this by adding this to your module xml file:
    <extend-property name="locale" values="nl_BE"/>
    <set-property name="user.agent" value="gecko"/>

  • Get a faster computer, it really helps. On my Pentium 4 2.8 Ghz, it took 30 seconds to compile. On my brand new Dual Core 2.6Ghz with 2 RAID disks, it takes 5 seconds. Considering the number of times you compile, it really makes it much more fun to develop.

  • There is also a "hosted mode" which runs the code as Java, without compiling to javascript. I don't use this anymore because (for my project) it takes longer to start up than simply compiling to javascript and it's more difficult to integrate with a backend.

  • I did integration with Spring for the RPC calls by extending RemoteServiceServlet and overriding the method processCall:

    public String processCall(String payload) throws SerializationException {
    initialize();
    try {
    RPCRequest rpcRequest = RPC.decodeRequest(payload, AjaxService.class);
    return RPC.invokeAndEncodeResponse(this.ajaxService, rpcRequest.getMethod(),
    rpcRequest.getParameters());
    } catch (IncompatibleRemoteServiceException ex) {
    return RPC.encodeResponseForFailure(null, ex);
    }
    }


  • AJAX pages don't work well with Google indexing and Google Adsense. For that reason, I created seperate pages for the search results instead of putting the whole site on one page. I also added noscript tags to the html with a plain html result.

Labels: , , ,