The intersection of technology and leadership

Category: Development (Page 9 of 18)

Speaking at QCon London 2011

This year marks the 5th QCon London conference to be held on March 7-11, 2011. The program is full of strong and interesting topics. This year, I’ll be speaking on the Software Craftsmanship track.

I’ll avoid getting drawn into the arguments around all the blog posts going back and forth about whether Software Craftsmanship is a craft, and whether or not it’s good or bad in its current incarnation. I’ll assume that people attending this track care about getting better at what they do, focusing on how you go about doing this with a talk, “The Beginner’s Mind“.

Better yet, save £100 by using the following code to register: KUA100. Hope to see you there.

It’s never been about what you do

I find it fascinating talking to people about their agile implementation. Some people immediately claim they’re agile by describing the practices they use. I often ask a few more questions such as, “How is that working for you?” and they start to describe a number of problems they have. Another answer people often give is, “We’ve been doing agile for ages!”

“Doing agile” has never been the point. The agile mindset is about working with customers or stakeholders to deliver solutions whilst always continually improving. The practices are simply ways of getting there. It’s never been about what you do. What matters is how you do it.

Improving how you do something is easy yet requires constant discipline. First, you need to be continually asking yourself, “How does this practice help us?” and searching for answers to another, “How can we get better at this?” Talking to people outside your organisations often help, as does following what other people do around the world (made easy through social channels like twitter and blogs).

Thoughts On Øredev

Last week Sweden’s Malmö hosted Øredev for the sixth time. I believe it attracted more than 1400 people, all with varying backgrounds and interests. Unsurprisingly, the majority of attendees turned out to be Swedish and Danish people (with Malmö very well connected to Denmark via their famous Baltic Ocean crossing train).

The Cultural Experiences
Being held in Sweden, the organising committee did well to treat us to some cultural delights including the Swedish sauna-Baltic Ocean run followed up by a delicious traditional fish meal). One of the organising members even welcomed us into their home for drinks before the speakers’ dinner where Glögg continued to keep the cold at bay. The difference of soaking raisins and almonds really surprised me. Malmö’s deputy mayor then welcomed us at their majestic townhall where all the speakers unanimously marvelled at the decadent surroundings. The meal stayed true to the region with first, a regional speciality, black soup (and yes, like black pudding, it has a very special ingredient) before following that up with a hearty roast goose meal and a spiced apple pudding for dessert.

Logistics and Organisation
The organisers impressed me with how smoothly the entire conference ran. Malmö’s Slagthuset (slaughterhouse) hosted the conference for the first time and although not all the spaces turned out ideal (with small walkways between some major rooms), I think it contributed to the friendliness and openness I discovered.

The organisers also did a fabulous job responding to attendee’s needs. For example, on Monday they moved a number of tutorials to warmer rooms after realising the strong draughts let in by workmen who still needed to complete their work. Another example is when they quickly disabled the authentication on the wi-fi when it proved to be another barrier to being connected. Unfortunately the wi-fi turned out to be a little bit flakier throughout the conference.

I also really enjoyed the evening entertainment that flowed into the venue rather than the “move to another location and lose people” approach several other conferences do. This helped to keep the conversation flowing (and we all love our flow!).

Topics
Øredev offered a huge variety of interesting topics with tracks covering mainstream languages such as Java/.Net, NoSQL, Agile & Lean, Collaboration, Patterns, Smart Phones and Architecture with lots of really interesting topics. I’d keep an eye out for their website and trawl the twitterverse (#oredev) for the interesting discussions.

The keynote presenters also turned out really well.

Dr Jeffrey Norris presented what he thought as agile values leading to mission critical success at NASA (Vision, Risk and Commitment) demonstrating through a “wow” 3D demonstration using the ARToolKit. He used the stories of famous inventors, particularly the rise of Graham Alexander Bell to emphasis these elements very effectively.

I saw John Seddon a few months ago and although I’d heard him present pretty much the same talk, appreciated his message was an important one that more people really needed to hear. I think there is great value in spreading his emphasis on holistic system thinking even further in the work that we do. Entertaining and very British, Seddon completed his keynote without leaning on any slides and to a very positive reaction from the audience.

I missed Henrik Kniberg‘s keynote so can’t really comment.

The final keynote came from Atari Corporation geek legend Nolan Bushnell envisaging what the next key software projects would be in the future. I think everyone enjoyed the talk simply because it was Nolan though I think wasn’t as executed as professionally as it could have been.

People to meet
One of the really great parts of Øredev was all the people around you. As one person put it, you could be talking to a person and then suddenly realise that they created X (where X = language, framework, tool, etc) or someone who wrote a lot of the blog entries that you’ve been reading. I think that the conference does a wonderful job of creating a really relaxed atmosphere for people to converse and the speakers are all really approachable and involved in all of the sessions as well.

I have to admit I also really appreciated the opportunities to connect to a number of fellow ThoughtWorks colleagues (both past and present) who I’d either not got a chance to meet, or hadn’t seen for a very long time. This is one of the consequences of working for a global consultancy – you get to communicate and build relationships for a distance yet rarely get to meet people face to face.

iPad observations
One huge point worth noting was the large role that the iPad played during this developer conference. Obviously, being fairly geeky I hadn’t expected so many of them yet it proved to be one of the best devices for capturing notes & particularly useful for reading and contributing tweets. Laptops lose out on both portability and, on average, a very so-so battery life.

Reading tweets to view session using the native iPad twitter client also worked really well without having to use the keyboard or mouse – this is where gestures and multi touch really shined.

My session
Chris Hedgate, organiser for the track on collaboration invited me to speak. Titled, “Tightening the Feedback Loop“, I spoke about how to give and receive more effective interpersonal feedback. I had some great tweets in response and some great feedback on the presentation (meta!) I’m encouraged that more people will be better equipped in their professional and personal life after attending.

Conclusion
I highly recommend presenting and/or attending Oredev. You’ll meet a whole heap of really interesting people and, no doubt, come away with at least an idea or two.

Just one more thing

As a developer, there’s a tension between doing things consistently and knowing when to make change. Consistency generally means it’s easier to understand – there’s only one pattern for people to learn and then the next time they see something like it they have a pretty good guess at how it’s going to work.

People also generally learn by copying – and therein lies the problem for inexperienced developers. They look at what’s there, figure it’s better to follow the established pattern and then to add just one more thing. Generally it doesn’t really matter what it is – another branch to a if statement, another parameter to a method, another function to class, or another (ugh!) static call.

Responsible, experienced developers know where the inflection point is – where the right thing to do is to refactor the code, and to avoid adding just one more thing.

Presented at Universite du Si

It’s almost three weeks ago I presented at USI2010 (Universite du SI). Organised wonderfully by the Octo consulting company, the conference’s tag line, “The Annual meeting of Geeks and Bosses” captures a really good essence. Mix over conferences and events are important to ensure that communities don’t silo themselves in ways that prohibit their growth. The complexity and chaos community clearly demonstrated the value of idea cross-pollination between between professions with their think tank, the Santa Fe Institute. This event is definitely the seeds of something good like this.

To add to the mix, I had the opportunity to present my session on Building the Next Generation of Technical Leaders here. This is the first conference I’ve been to where the majority of the session were not in English. This made me think a lot about how memes spread, and how quickly this affects how adaptable a community is.

I think it is wonderful for this conference to invite speakers from non-French speaking backgrounds, as I hope that it helped seed some more ideas into a community where translating text into a local language hinders the uptake of new ideas. I know that it is much more difficult for people to understand a language other than their native tongue and I can only admire those French people willing to strike up a conversation with me during the conference where my study of the French language is what tourist books teach.

The conference was very well run and although I would like to comment much more on the presentations since most of them were in French. If you understand French, and you find yourself near Paris, then I think it’s an excellent one to attend.

Downloading specific files through Maven

In ant, it’s pretty easy to use the ant task get to download something for you. Apparently it’s not something most maven users do (probably because they end up doing something like an ant=run). Even though maven has in-built web communications (this is how it often is found downloading the interweb), it wasn’t easy finding out how to download something not in a maven repository (without having to deploy artefacts into a maven repository which I understand is the “maven way”).

Anyway, after sometime, here’s the plugin configuration I used to do the download. Note that we’re using Maven 2.1.0 (and it could have changed in the latest version).

The following plugin will download configuration.jar and artifact.jar from the web directory http://host/pathToArtifact and drop it into a folder called target/downloadedFiles. This does this at the start of the maven lifecycle (note the phase it is attached to below).

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>wagon-maven-plugin</artifactId>
	<version>1.0-beta-3</version>
	<executions>
		<execution>
			<phase>validate</phase>
			<goals>
				<goal>download</goal>
			</goals>
			<configuration>
				<url>http://host/pathToArtifact</url>
				<includes>
					configuration.jar, artifact.jar
				</includes>
				<toDir>target/downloadedFiles</toDir>
			</configuration>
		</execution>
	</executions>
</plugin>

Some limitations is that it won’t fail if it can download some of the artifacts and not others.

Executable War in Maven

One of the many issues I had (have) with Maven is finding out how to use an appropriate plugin. The site documentation is normally pretty obscure, and examples are sparse. One of the activites we needed to do recently is to turn our war artifact into something that would run standalone. I’d normally use something like jetty for this but I didn’t find a way to easy bundle jetty and refer to the war within the same classpath (and still have things work).

Another tool I stumbled across was winstone (Hudson uses this beast). Wrapping this up seemed pretty easy enough. Note that the configuration below is used to start a war that won’t have dynamic JSP compilation. If you do, you can add a useJasper=true configuration and add the appropriate maven dependencies for jasper to ensure they’re available.

The result of this plugin will effectively build an executable jar, that you simply start up.

Need to add these dependencies:

Given that your project is a war package as well

&amp;lt;plugin&amp;gt;
	&amp;lt;groupId&amp;gt;net.sf.alchim&amp;lt;/groupId&amp;gt;
	&amp;lt;artifactId&amp;gt;winstone-maven-plugin&amp;lt;/artifactId&amp;gt;
	&amp;lt;executions&amp;gt;
		&amp;lt;execution&amp;gt;
			&amp;lt;goals&amp;gt;
				&amp;lt;goal&amp;gt;embed&amp;lt;/goal&amp;gt;
			&amp;lt;/goals&amp;gt;
			&amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;
		&amp;lt;/execution&amp;gt;
	&amp;lt;/executions&amp;gt;
	&amp;lt;configuration&amp;gt;
		&amp;lt;filename&amp;gt;executableWebApplication.jar&amp;lt;/filename&amp;gt;
	&amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;

You will find this artifact built in your standard target directly.

Who’s calling you?

I’ve been working on some performance testing profiling and in trying to diagnose a fix, we found one particular method was being called constantly. Searching for usages (static analysis) tells me who could possibly call the method we were inspecting, but we were interested in the runtime invocations. Since this was quite deep in the code, I used the power of dynamic proxies to do this.

I’ve rebuilt the code here:

Source:

package com.thekua.examples;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TraceBackProxy implements InvocationHandler {
    public static interface CallingMethodListener {
        void notify(String method);
    }

    private final Object wrapped;
    private final CallingMethodListener listener;

    private TraceBackProxy(Object wrapped, CallingMethodListener context) {
        this.wrapped = wrapped;
        this.listener = context;
    }

    public static Object wrap(Object target, CallingMethodListener context) {
        Class targetClass = target.getClass();
        return Proxy.newProxyInstance(targetClass.getClassLoader(),
                targetClass.getInterfaces(), new TraceBackProxy(target, context));
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {
        String callingMethod = findCallingMethod(method);
        listener.notify(callingMethod);
        return method.invoke(wrapped, arguments);
    }

    private String findCallingMethod(Method method) {
        try {
            throw new RuntimeException();
        } catch(RuntimeException e) {
            StackTraceElement[] elements = e.getStackTrace();
            int callingMethodIndex = findIndexOfMethod(elements, method) + 1; // caller is next one down in stack
            return elements[callingMethodIndex].getMethodName();
        }
    }

    private int findIndexOfMethod(StackTraceElement[] elements, Method method) {
        for (int i = 0; i < elements.length; i++) {
            StackTraceElement current = elements[i];
            // does not cope with overloaded or duplicate method names
            if (current.getMethodName().equals(method.getName())) {
                return i;
            }
        }
        throw new IllegalStateException("Something went wrong and couldn't find method in stacktrace");
    }
}

Test:

package com.thekua.examples;

import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;

public class TraceBackProxyTest {

    public static interface SomeRole {
        void doStuff();
    }

    public static class TestSubject implements SomeRole {
        public boolean called;

        @Override
        public void doStuff() {
            called = true;
        }
    }

    @Test
    public void shouldStillDelegate() {
        TestSubject target = new TestSubject();
        SomeRole action = (SomeRole)TraceBackProxy.wrap(target, new TestOnlyListener());

        action.doStuff();

        assertThat(target.called, is(true));
    }

    public static class TestOnlyListener implements TraceBackProxy.CallingMethodListener {
        String lastCalledMethod;

        @Override
        public void notify(String method) {
            lastCalledMethod = method;
        }
    }

    @Test
    public void shouldFindCallingMethod() {
        TestOnlyListener listener = new TestOnlyListener();
        SomeRole action = (SomeRole) TraceBackProxy.wrap(new TestSubject(), listener);

        action.doStuff();

        assertThat(listener.lastCalledMethod, equalTo("shouldFindCallingMethod"));
    }
}

Note that your mileage may vary since it probably won’t work when you have duplicate method names across classes, or overloaded methods on the same. It proved useful for me and hope it helps you.

Refactoring: Convert static into instance

You want to ensure reusing functionality does not have any other side effects in other places that might be using it.

Make the static instance explicit by introduce a static instance encapsulating any static state and delegate items to it. Use the instance.

Imagine you had this sort of code (below) and there’s dozens of use throughout a codebase. Static imports make it easy for people to simply increment a count, but in order to use the Counter, you have no assurance nothing else will try to use it.

public class Counter {
  static int totalCount;

  public static void count() {
    totalCount++;
  }
}

The following transformations will help you keep existing clients happy:

  • Introduce new method (instance level)
  • Introduce global instance
  • Delegate static method to new method (instance level)
  • Turn static state into instance state

The final result is below (note that this code is not thread-safe and not designed for concurrent programs, but is there to demonstrate the result of the refactoring steps):

public class Counter {
   private static final Counter INSTANCE = new Counter();

   private int totalCount;

   public static void count() {
     INSTANCE.recordCount();
   }

   public void recordCount() {
     totalCount++;
   }
}

Now we had a bit more of a complex example, but this refactoring helped us move to the right direction of using instances where possible, instead of sharing global state.

« Older posts Newer posts »

© 2024 patkua@work

Theme by Anders NorenUp ↑