try {} catch ()

Java, Agile, the Web and other nice things

Jun

9

A few things about Scrum…

By Olivier Gérardin

I recently attended a very interesting 2-day Scrum Master course with Dan Rawthorne, a seasoned agile practitioner, and that made me realize that Scrum is a living thing and has evolved from what I thought I had figured out, and is still evolving… Dan has a lot of experience managing agile projects and is one of the people shaping Scrum day after day. He has a book in preparation which I’m eager to get my hands on.

So, what I was familiar with and had put in practice was what Dan called “Grandpa’s Scrum”, which is actually the original version of Scrum. Nothing wrong with that, but Scrum has been refined since and a few subtle but important changes have made their way into Scrum.

Also, the course made me understand some of the misconceptions I had about Scrum.

So, here are, in no particular order, some points that were mentioned and that I found noteworthy:

  • The sprint backlog is not untouchable! Just because you agreed during sprint planning on what you were going to try to achieve in this sprint, doesn’t mean it can’t change during the sprint… Reality might knock in and force you to change the priorities. What if the server room is on fire? Are you still going to try to stick to the initial plan? Of course not. In any case, the Product Owner is the only one who is allowed to change the priorities, and he can do so at any time, even during a sprint!
  • The “product backlog” is actually called simply the “backlog”, because it does not only contain items about the product, but anything that needs to be done! Similarly, “user stories” are now only “stories”, because they’re not necessarily about the product directly. You might also find them referred to as PBIs (product backlog items). While these terminology changes might seem minor, I think they are necessary because they influence our understanding of Scrum.
  • Stories need to have a “definition of done”, that is a list of conditions that the team agrees will mean the story is, well, done. This might seem obvious or implicit but it is not, because this definition might include some points that are not directly related to the implementation of the story but are crucial nonetheless, such as making sure it’s tested, making sure the code is committed, making sure the code has been reviewed, etc.
  • The Product owner is an integral part of the team! Which means he can’t be on te business side; that would be the Business Owner. The Product Owner is responsible for communicating with the Business Owner, translating his wishes into stories, and prioritizing them. In return the PO is the single person accountable to the BO for how the product is evolving.
  • Estimating stories is (at best) useless, unless you want to fall back in the old waterfall / plan everything ahead model. What matters is: do you want to implement it, or not? Only tasks that derive from stories can be estimated, for the sake of knowing if they will fit in a sprint or not. Stories need only be prioritized.
  • “Backlog grooming”: that’s the action of cleaning up, refining and re-prioritizing the backlog. Of course it’s something everyone does, but it feels good to have a name for it :)
  • Burndown charts are avoidable: since the beginning I found them unnatural; what, a chart going down?? Plus burndown charts actually measure activity, not progress. What do you want to know, how busy the team is, or how fast is the project moving? I assume the latter, then the only thing you’re interested in is how fast stories are solved, period.
  • Subject Matter Experts (SMEs) can also be technical experts (architects, DBAs, …), they’re not necessarily experts in the application domain.

Finally, a note on the Scrum Master role, which this training was mostly bout. This is always the most challenging role to explain to a non-Scrum person, because it has so many aspects, and can’t be appropriately summarized other than saying he’s a “facilitator”… An interesting (and quite sexist, but let’s keep that aside) analogy is that of the family: if you consider the team as a family, then Scrum Master would be the mom: taking care of everyday tasks so that the house is well-run, the children (other team members) are well behaved and play nice with each other, etc. In this analogy the Product Owner would be the dad, maybe away working for part of the day (actually, talking to the Business Owner, stakeholders and SMEs…) but having the last word on what needs to be done and when.

In any case, if you can attend one of Dan’s conferences or training classes, this will be time well spent.

Story: Scrum Master Certification course. Done. Next…

 

Mar

30

Java in Flux… a Java roadmap (kindof)

By Olivier Gérardin

Must read keynote from the TSSJS conf last week… I was thrilled by the Aeon Flux reference btw :)
[edit: the presentation has been removed and is no longer accessible... you can read the related blog entry here. Thanks Chris for making me aware of this]


Mar

25

Download Chrome extension from other browser (for offline installation)

By Olivier Gérardin

This is a little trick I found nowhere on the web so I thought I’d share.

Suppose you need to install an extension for Chrome, but for some reason you can’t access internet from Chrome itself… Easy, you just need to get the CRX file that contains the extension bundle, right? The trouble is, you can’t easily get this file if you’re browsing the extension gallery with anything other than Chrome.

 

Here’s how I did it:

  1. Find the ID of the extension you’re interested in. When on the details page of the extension, it will be something like “bfbmjmiodbnnpllbbbfblcplfjjepjdn” after “https://chrome.google.com/extensions/detail/” in the page URL
  2. Paste this URL into your browser: “https://clients2.google.com/service/update2/crx?response=redirect&x=id%3D____%26uc” replacing ____ with the extension ID.
  3. You’ll be prompted to save a CRX file. Drag this file to a Chrome window and proceed with installation

Done!

Sep

21

GWT Designer now available for free!

By Olivier Gérardin

In case you missed it, Google announced last week that the tools from the rcently acquired company Instantiations were now available for free!

This is a great news because it includes GWT Designer, the famous (and only so far) graphical designer for GWT… It’s the perfect complement to the Google plugin for Eclipse.

Google Web Toolkit Blog: Google Relaunches Instantiations Developer Tools – Now Available for Free.

Aug

6

About Google Wave’s end

By Olivier Gérardin

You probably know that Google has recently announced that they were stopping development for Google wave, and indeed after the initial buzz and all the hype that surrounded wave when it was launched, interested faded rapidly.

Why did that happen ? I mostly agree with this post: Why Google Wave “failed”.

When users need to say things like “To understand what Wave is, you have to either use it or watch the video; it’s impossible to explain“, you should know that something is wrong with your product. To survive and proliferate, products need a clear purpose that everyone can understand.

It doesn’t mean that Wave’s purpose was not smart or that it didn’t have any usefulness, but it could mean that Wave was too much in advance for its time. There are a lot of examples of inventions that didn’t prove successful when they were first published, but only later when the time was ripe for it. If you tried to explain what Twitter is no more than 20 years back, I bet you’d have the same difficulties in communicating Twitter’s purpose than Google had trying to explain what Wave was.

E-mail is so popular because it’s simple: self contained messages sent back and forth between individuals, forming conversations. But these conversations have limits that Wave tried to lift: not real-time, no central archiving, no plugin, little automation… unfortunately, a wave is both too similar and too different from an e-mail conversation for most people to see a clear benefit.

But this alone can not explain Wave’s lack of success; there were also some bad choices in UI design. Google is (was?) well known for its spartan yet functional UI design, which is exemplified in Google Search for example or GMail. No fancy animations or drag and drop or big icons, just functional buttons, at the exact right position, with the exact right size and font so that you’re not distracted from your goal.

Wave was the exact opposite: unintuitive and confusing interface, with minimizing  frames (why on earth?), trying too hard to unify concepts (my settings is a wave? come on!). I’m sure that after receiving their long-awaited invitation, most users connected once, tried to figure it for a while and then gave up and never came back. I’d be curious to know the stats…

Anyway, I’m sure that Wave will resurface in one form or another, because it is a response to one of the biggest challenges of communication these days: the scattering of information and ways to communicate. The need is there, just waiting for the right product when the time is ripe…

Jul

2

Testatoo: TDD for the GUI

By Olivier Gérardin

Test-driven development is a good thing. We all agree on that, right?

But TDD assumes you can write tests before actually implementing the functionality. How do you do for the GUI when most GUI test tools are based on a scenario-recording appraoch? This requires that the GUI already exists; in other words, another instance of the “chicken or the egg” dilemma…

My friend David Avenante (and host in Montréal for the confoo.ca 2010 conference), has been working on a solution to this problem called Testatoo.

From the web site: “Testatoo provides on one hand an abstraction of the UI business domain through an expressive API and on the other hand a way to express this domain via a DSL (a button semantically stays a buttons whatever the technology). With Testatoo you can therefore write tests with a seldom achieved level of expressiveness and make these tests INDEPENDENT of the underlying technology.”

Interested? The testatoo web site is now up, with tutorials, demos, samples, FAQ, and a forum ! Give it a try, and post your feedback…

May

16

Slides from my GWT2 presentation at YaJUG

By Olivier Gérardin

Apr

9

GWT: using JSON as history token?

By Olivier Gérardin

As you might know, GWT provides a handy and elegant mechanism to manage back and forward buttons (and bookmarking) through the use of the “anchor” part of the URL, that is the part after the # sign. Basically, whatever you put after the # will not trigger a page reload, but can be intercepted by JavaScript.

Using it in GWT is very straightforward:

  • register a listener to be notified when the context changes (user pressed back or forward or jumped in history) with History.addHistoryListener(listener)
  • when you want to create a browser history savepoint, call History.newItem(token)

The only thing is, GWT will not generate the token for you, because it has no way of knowing what must be included in the so-called application state. So when you want to manage history with GWT, you should always ask yourself the following questions:

  1. What must be saved? (just the active window? the selected item? etc.)
  2. How will you encode this in a String?

Depending on how complex is your answer to question 1, the answer to question 2 can be very trivial. For example, if all you want to save is the active tab in a multi-tab app, then the contents of the history token can be just an identifier of this tab. Generating it is easy, and so is parsing.

But what if you have more complex data, such as a list of items you want to restore, plus the currently selected item, plus the active view, etc.? I’ve been looking for a generic way to build a history token in such a case for a while. At first I considered a simple list of key/value pairs, such as:

key0=value0; key1=value1

This will certainly work in simple cases; you could write a parser and serializer that takes or generates a Map<String, String> without too much trouble. But then inevitably will come the need to embed another map (or a list) in the map… then the simple case is not so simple anymore.

Anyway, you could imagine handling recursivity with a format like :

key0=(item00, item01), key1={key10=value10, key12=(item120, item121)}

which would be parsed as:

  • map
    • key0 -> list
      • “item00″
      • “item01″
    • key1 -> map
      • key10 -> “value10″
      • key12 -> list
        • “item120″
        • “item121″

you get the picture.

I was set to write a parser for this type of format, and not very happy to have to do so, when it struck me how close this format was to JSON… what if a map was a JSON object, a list a JSON array ? My previous example would then generate the following JSON string:

{“key0″:["item00"," item01"], “key1″:{“key10″:”value10″, “key12″:["item120"," item121"]}

Given that GWT comes with a JSON parser/serializer, if I can represent my application state as a Map<String, Object> where objects are instances of String, List<Object> or Map<String, Object>, it would be very easy to build a JSON representation of it. Would that work?

The short answer: yes, but there are caveats.

First, since most of the special characters are URL-encoded, it’s not pretty. Actually it’s really ugly. This is what it looks like on an example:

MyPage.html#%7B%22active%22:%222d22aa%22,%20%22selected%22:%222dff8%22,%20%22workFolder%22:%5B%222be34%22,%222dff8%22,%22414a4%22%5D%7D

Scary, isn’t it? But, unless you believe every user pays attention to what’s going on in the address bar, it doesn’t really matter.

Second, it’s pretty verbose. The URL can’t grow in length indefinitely, and this burns a lot of precious characters.

Third, it’s not secure, if you use GWT’s native JSON parser that is, because as stated in the Javadoc: “For efficiency, this method [parse] is implemented using the JavaScript eval() function, which can execute arbitrary script. DO NOT pass an untrusted string into this method.”.

The last one is a showstopper for public web sites, unless you reimplement your own JSON parser in GWT. So yes, it works, but no, don’t use it. And if you do anyway, don’t blame me.

If you want some detail here’s how I have done it. I’m in the context of a HMVC app; each controller has a getState() method which is supposed to return a Map representing its state to be saved, and a restoreState() method that takes a Map of the state to be restored. By default getState() returns an empty map, and restoreMap() does nothing, so subclasses are free to override those methods to provide something to save/restore (which might recursively include the state of subcontrollers).

The topmost controller is responsible for handling save state requests; it uses getState() to obtain the global application state, then converts it to a JSON representation, and calls History.newItem().

Conversely, when a history change is detected, the token is parsed as JSON and then converted to a Map. The result is passed to restoreState(), which takes what it needs from the map, does what is needed to restore the state, and recursively calls restoreState() on subcontrollers. How neat is that?

Here’s the code I use to convert my object graph that represents the app state to and from JSON:

    /**
     * Serialize the specified object as a JSONValue. The object to serialize must be an instance of:
     * - String
     * - Map
     * - List
     * 

* where O has the same constraints. */ public static JSONValue serializeAsJson(Object object) { if (object instanceof Map) { Map map = (Map) object; JSONObject jsonObject = new JSONObject(); for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); JSONValue convertedValue = serializeAsJson(value); jsonObject.put(key, convertedValue); } return jsonObject; } else if (object instanceof List) { List list = (List) object; JSONArray jsonArray = new JSONArray(); for (int i = 0; i < list.size(); i++) { Object entry = list.get(i); JSONValue convertedValue = serializeAsJson(entry); jsonArray.set(i, convertedValue); } return jsonArray; } else if (object instanceof String) { return new JSONString((String) object); } else { throw new RuntimeException("Unsupported state type: " + object.getClass()); } } /** * Parse a JSONValue as follows: * -if the value is a JSONObject, parse into a Map * -if the value is a JSONArray, parse into a List * -if the value is a JSONString, parse into a String * -otherwise fail */ public static Object parseObject(JSONValue jsonValue) { if (jsonValue.isObject() != null) { return parseMap(jsonValue.isObject()); } else if (jsonValue.isArray() != null) { return parseList(jsonValue.isArray()); } else if (jsonValue.isString() != null) { return jsonValue.isString().stringValue(); } else { throw new RuntimeException("Failed to parse JSON: " + jsonValue.toString()); } } /** * Parse the specified JSONObject into a Map. The JSONValue associated to * a key is parsed recursively using {@link #parseObject(JSONValue)} */ public static Map parseMap(JSONObject jsonObject) { Map result = new HashMap(); for (String key : jsonObject.keySet()) { JSONValue jsonValue = jsonObject.get(key); Object convertedValue = parseObject(jsonValue); result.put(key, convertedValue); } return result; } /** * Parse the specified JSONArray into a List. The JSONValues contained in the array are * parsed recursively using {@link #parseObject(JSONValue)} */ public static Object parseList(JSONArray array) { List result = new ArrayList(); for (int i = 0; i < array.size(); i++) { JSONValue jsonValue = array.get(i); Object convertedValue = parseObject(jsonValue); result.add(convertedValue); } return result; }

Mar

22

Google and Palm: the ideal scenario

By Olivier Gérardin

It was suggested by Phil kearny (ex Apple employee) that Google should buy Palm…

Let’s dream a little bit:

  1. Google buys Palm
  2. A GWT wrapper is developper for Mojo (Palm’s Javascript SDK). GWT becomes the official SDK for webOS
  3. dalvik is ported to webOS. All the apps from the Android marketplace are now available for webOS devices
  4. Android and webOS merge. Android 3.0 runs both dalvik apps and Mojo/JavaScript/GWT apps
  5. Google releases the most amazing smartphone ever, the Nexus Ultimate. The iPhone is now a thing of the past.
  6. Apple open sources the iPhone SDK, allows Flash on their mobile devices, opens up the AppStore for all apps, and goes back to what they do best: desktop and laptop computers, with a reliable UNIX-based OS.

PS: after I wrote this post, I found that some rumors were spreading about Palm moving to Android… I promise I’m not the one who wrote the fake “anonymously sourced, unconfirmed memo” ;)

Mar

17

Tim Bray now a Google employee

By Olivier Gérardin

For those of you not familiar with the Who’s Who of IT, Tim Bray is best known for the central role he played in the initial specification of XML. I should know because I spent countless hours studying it back in 2000. If you really really have to read it too, I urge you to read instead the annotated XML specification, with invaluable insight from said Tim Bray. Almost entertaining compared to the plain spec…

Anyway, Tim joined Google with focus on the Android platform. I’m glad to see that we share the same feeling about the iPhone and Apple’s AppStore policies:

The iPhone vision of the mobile Internet’s future omits controversy, sex, and freedom, but includes strict limits on who can know what and who can say what. It’s a sterile Disney-fied walled garden surrounded by sharp-toothed lawyers. The people who create the apps serve at the landlord’s pleasure and fear his anger.
I hate it.

While I don’t have much hope that this reality will ever bother the vast majority of iPhone users, I strongly hope that more and more developers move away from the iPhone because of the way Apple treats them.

I’m sure Tim will add to the reasons to move to Android…