Most irritating bug of my life

Maybe not the worst I’ve seen, but it’s in the top 10, definitely. As I was unable to find any help on the Internet, it might help someone someday, so here it goes.

Currently, I’m working on an RCP + Spring + OSGI project. After a large-scale integration, I was getting the following exception at startup:

!ENTRY org.eclipse.ui 4 0 2011-08-10 10:46:59.838
!MESSAGE Unhandled event loop exception
!STACK 0
java.lang.NullPointerException
        at org.eclipse.ui.internal.handlers.HandlerProxy.loadHandler(HandlerProxy.java:352)
        at org.eclipse.ui.internal.handlers.HandlerProxy.setEnabled(HandlerProxy.java:231)
        at org.eclipse.core.commands.Command.setEnabled(Command.java:857)
        at org.eclipse.ui.menus.CommandContributionItem.isEnabled(CommandContributionItem.java:918)
        at org.eclipse.ui.menus.CommandContributionItem.updateToolItem(CommandContributionItem.java:611)
        at org.eclipse.ui.menus.CommandContributionItem.update(CommandContributionItem.java:528)
        at org.eclipse.ui.menus.CommandContributionItem.fill(CommandContributionItem.java:503)
        at org.eclipse.jface.action.ToolBarManager.update(ToolBarManager.java:353)
        at org.eclipse.jface.action.ToolBarManager.createControl(ToolBarManager.java:111)
        at org.eclipse.jface.action.ToolBarContributionItem.fill(ToolBarContributionItem.java:192)
        at org.eclipse.jface.action.CoolBarManager.update(CoolBarManager.java:928)
        at org.eclipse.jface.action.CoolBarManager.createControl(CoolBarManager.java:247)
        at org.eclipse.jface.internal.provisional.action.CoolBarManager2.createControl2(CoolBarManager2.java:76)
        at org.eclipse.jface.window.ApplicationWindow.createCoolBarControl(ApplicationWindow.java:523)
        at org.eclipse.ui.internal.WorkbenchWindow.createDefaultContents(WorkbenchWindow.java:1053)
        at org.eclipse.ui.internal.WorkbenchWindowConfigurer.createDefaultContents(WorkbenchWindowConfigurer.java:625)
        at org.eclipse.ui.application.WorkbenchWindowAdvisor.createWindowContents(WorkbenchWindowAdvisor.java:268)
        at org.eclipse.ui.internal.WorkbenchWindow.createContents(WorkbenchWindow.java:1000)
        at org.eclipse.jface.window.Window.create(Window.java:431)
        at org.eclipse.ui.internal.Workbench$20.runWithException(Workbench.java:1032)
        at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
        at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
        at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:134)
        at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3885)
        at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3506)
        at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803)
        at org.eclipse.ui.internal.Workbench$28.runWithException(Workbench.java:1384)
        at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31)
        at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
        at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:134)
        at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3885)
        at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3506)
        at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2316)
        at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221)
        at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
        at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493)
        at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
        at xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(Application.java:60)
        at xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(Application.java:36)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1311)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1287)
Not that self explanatory, is it? After a week of try-error cycles, it turned out that Spring’s configuration.xml was missing a bean (thank you, automatic merge…), so Spring context was unable to start up. It has thrown an exception that was caught by the RCP framework. After correcting the XML file, the application magically got well… I wish these frameworks could work together and give valuable error messages…
Advertisements

Agile development and UML

In case of agile development, we usually don’t run into hundreds of lines of documentation, with detailed diagrams, architecture proposals etc. This is good for several reasons; developers can use their creativity in order to materialize requirements. This way, people won’t fall into the pitfall of blindly following someone’s vision either.

However, UML may become in handy at feature development. With just a small investment (as low as the price of a whiteboard) a team can boost their productivity. This is how: promote a whitheboard as “design board”. The design board has no other role, than to store the current architecture of the feature under development. It, of course,  supposes that each and every team member updates the board whenever they make a change to the current state.

One might argue that there are a lot of software tools out there, why not use those? Well, the answer is simple; people are lazy (and forgetful, in the same time). Even if the UML diagram is stored somewhere everyone has access to, they won’t open it, let alone update it. They simply forget it, becouse the thing is not in front of their eyes all day long. However, if it is present materially, people actually tend to update it on a regular basis (also, daily standup meeting is a really good period to remaind everyone to do so, in the case they somehow forget it). The diagram doesn’t have to be that detailed. It’s perfectly enough if it contains the classes and interfaces, associations (uses, implements, extends …) and main methods.

How does this help increase velocity? Simple. People don’t have to randomly open different classes in order to find the right one to place some new code in. They just take a look at the board and know immediately how classes are related, which is the right one for the new logic. They also don’t have to remember all the class names and the relationships between the different components. Planning meetings (along with task breakdowns) will also get shorter. It eliminates the phrases that start with the infamous “well, I guess…” stuff; people will talk about facts not beliefs. Less stress, less time spent on arguing.

Prototyping vs TDD Prototyping

I often hear “I’m prototyping” as an excuse not to do TDD. In this context prototyping means  “there will be no unit tests around this piece of code, ever”.

In my opinion prototyping does not mean avoiding writing tests at any price, but to

  1. Create a piece of code without tests and  check whether it works or not. If it does not, make it functional and – here it gets tricky – delete/comment out the whole thing. After that recreate the certain functionality using TDD practices. This process is kind of laborious and can be used when the functionality being implemented cannot be decoupled from the system. This approach can be employed when the functionality being implemented depends on a third party product, where the communication protocol is unclear.
  2. Create an application totally outside the boundaries of the system. The prototype application can be created with no test cases at all. It is because the prototype is not part of production code; it doesn’t matter for example if the code is not in a good shape because it is not part of the system and there is little chance that it will be read or modified by anyone other than its creator. Since the application is decoupled from the system under development it should be fast to run and see whether it produces the correct output (in less than five minutes, for example). The idea behind such a prototype application is to be created as fast as possible (sometimes in order to decide whether a third party application should be used or not), so anything beyond the happy execution path can be omitted. When the prototype works perfectly, it can be either thrown away and rewritten in TDD, or refactored/tested thoroughly and inserted into the system (this is risky though; by thorough I mean really thorough with all kinds of exception handlings and so on).  Remember, this is not TDD anymore.

Basically, prototyping can be used when the functionality under development depends on a third party application. In my opinion, there’s nothing to prototype when dealing with parsing input commands, validating things, calculating hashes etc. In those cases the word “prototyping” is just a cheap trick not to write unit tests.

Self improvement group – some feedback

Well, the following post is about some feedback I’ve recently received on my activity regarding our self-improvement group. I was really about to abandon the whole thing, but my friend Lajos Fülep’s kind words made me continue.

In the last two weeks our little self development group was busy with a brand new topic: namely legacy code (legacy code in the sense of: “code that is working suspiciously, and have no tests around it.”).  Some time ago I’ve posted some really ugly code that is full of bugs and has no tests at all. As discussed there, two rounds should be taken: one for adding tests , another one for refactoring it (and fixing the numerous bugs the code contains).

The first round was a pair programming session. The task was to cover the code as much as possible, and spot the mistakes – spot but, don’t touch them (hint: there are at least four major bugs in there). This task can be implemented in an hour. After that, we choose a reference implementation for the second round.

The second round is done randori-based. It means that there is a single laptop along with a projector, while people keep rotating in front of the computer. Everyone is allowed to make a single change. A single change can be: extracting a method, extracting a class, renaming TWO methods, variables etc. Basically the “one change” rule can be adjusted as you wish. I was kind of afraid of this randori-session; I thought people would be afraid of being creative while all fellow group members are looking at them. However, it went really well; people kept saying “I want to stay, this was half a change only”. What is very important here is that anyone not in front of the computer can speak only after the next change to be made has been named by the person at the computer. This means that you cannot give tips what to be done next (only if it was requested explicitly), but can argue whether a change is needed or makes sense at all.

Here’s the feedback I’ve received (translated from Hungarian):

I found this session very useful. What I liked about it was the task itself.  It was cool we had to refactor an ugly piece of code. On the other hand it was very useful to me to see how other people were working and thinking. Way to go 🙂

Code refactoring in progress :-).

Don’t trust third party products

Some weeks ago @marcellhegedus and myself were doing a major refactoring on our code base. It took us long days, and we finally managed to get the code into a good shape. We split functions, extracted new classes, renamed methods and variables, deleted unused code. Besides cleaning out the code, we even made some optimizations to it. That optimization involved changing some of the API calls, so we didn’t have to read the database every time for every single piece of data. We found out that the API could check it directly whether an external object has a certain parameter or not, without reading its actual value. It was a nice and elegant shortcut that made that component reasonably faster. Continue reading “Don’t trust third party products”

Reflection based programming

Usually I don’t write about language specific things, but today’s post is an exception. It’s purely Java. Also, this post is not about clean code or something, just an opinion. You either take it as an advice, or just forget about these things; it’s up to you.

I understand that Java Reflection is a terribly useful API, and I don’t say by any means that we should stop using it. One should definitely be using it when developing framweorks that can accept different kinds of plug-ins. In such situations, reflection can be our best friend. However, it should be used with care. Continue reading “Reflection based programming”

Planning poker et al

You probably know, or at least heard of Planning Poker. It’s a very funny event; the whole team gets together with the product owner, who presents the upcoming user stories one by one. After each story presented, the team have to estimate the amount of work that should be done in order to complete that user story. Continue reading “Planning poker et al”