patkua@work

The intersection of technology and leadership

Page 36 of 53

Controlling Time: How to deal with periodic gaps

Some application logging is important enough to put regressions tests in place. For instance, when you shell out to other programs and you want to monitor the amount of time it takes. In this entry I’m going to demonstrate how you might test that you are correctly logging out the time taken to do some long running work. I’m going to assume that you already have a Clock concept in the system.

Let’s assume we’re trying to test the following block of code:

public void doSomeWork(Clock clock) {
  DateTime startTime = clock.now();
  executeSomeLongRunningWork();
  DateTime endTime = clock.now();
  long timeTaken = endTime.minus(startTime.getMillis()).getMillis();
  LOG.log(Level.INFO, "Time taken was %sms", timeTaken);
}

One approach would be refactor the above code, replacing the Clock with a StopWatch but I’m going to show a technique for testing this code without changing it. Instead, we are going to inject an AutomaticallyForwardingClock. Here’s the implementation:

public class AutomaticallyMovingForwardClock implements Clock {
  private final int periodToMoveForwardsInMs;
  private DateTime now;

  public AutomaticallyMovingForwardClock(DateTime initialStartTime,
      int periodToMoveForwardsInMs) {
    this.now = initialStartTime;
    this.periodToMoveForwardsInMs = periodToMoveForwardsInMs;
  }

  public DateTime now() {
    DateTime result = now;
    now = now.plusMillis(periodToMoveForwardsInMs);
    return result;
  }
}

So whenever anyone asks the current time from the Clock, it automatically shifts time forward by the specified amount. Now we can write a test that looks like this:

@Test
public void shouldLogTimeTakenForProgramToExecute() throws Exception {
  int periodToMoveForwards = 5;
  Clock clock = new AutomaticallyMovingForwardClock(new DateTime(), periodToMoveForwards);
  doSomeWork(clock);
        
  long expectedDuration = periodToMoveForwards;       
  assertThat(fetchLogEntry(), containsString("Time taken " + expectedDuration + "ms"));   
}

A few notes from above:

  • The test uses the Joda DateTime class.
  • The test uses the Hamcrest API
  • The test assumes you know how to retrieve the log message from a logger

Although I think that injecting a StopWatch is probably a better mechanism, I hope that this technique still proves useful for some people.

A model for understanding retrospective impact

Steven List asks the question, Are Retrospectives an Anti-pattern? Of course, retrospectives are a topic close to my heart so I naturally wanted to share my view of them. The conversation apparently started on the Kanban Development mailing list and Steven’s post already captures some great discussion. I won’t repeat it here, but I find the dialogue echoing the same sentiments about other agile practices and whether or not they’re useful. For me, it’s too extremist and not particularly helpful. They make it sound like you need to choose from two positions: Either you run retrospectives, or you don’t.

I think the more interesting question is, “When are retrospectives most useful?” To help explain my thoughts, I’ve put together the following: A Model for understanding Retrospective Impact (click on it for a slightly bigger view).

A model for understanding Retrospective Impact

What is a retrospective?
Being specific and clear about this term is important in the discussion about whether or not retrospectives are useful. Some people’s understanding of a retrospective can differ from other people’s depending on each of their experiences. The conversations on the Kanban list seem to imply retrospectives are solely an iteration focused ritual (and of course, there is no such concept of a Scrum or XP iteration in Kanban). Though I appreciate Kerth’s original definition, I think in the agile community, Derby and Larsen’s definition better captures its essence:

A special meeting where the team gathers after completing an increment of work to inspect and adapt their methods and teamwork.

I like this definition best because its ties the concept of improvement (inspect and adapt) based on a shared understanding (the team) according to some unstated time period (an increment of work, noting it’s not specifically tied to an iteration).

What is impact?
I think it’s also important to define the term impact. One of the definitions by the Oxford Dictionary seems most appropriate:

a marked effect or influence

I want to emphasis that you can have a high impact retrospective without necessarily taking a lot of time, and that the opposite is entirely possible too (a long retrospective with a low impact). Note that I’m not going to discuss how to run retrospectives that have the highest impact (a totally separate topic worth its own set of posts).

Effect of team dynamics
The state of the team has an enormous influence on the impact of retrospectives. A high performing team will naturally have better communication amongst its members, and are more likely to fix things that get in the way of their goal. There will naturally be better and more frequent individual improvements, identified and implemented more frequently without the call for a specific meeting. This doesn’t mean that retrospectives are never a practice they call upon. Rather, it’s a practice that has less impact as there are many other items in the toolkit that get called upon. Sometimes it’s important for the group to get together, establish a common understanding and to inspect and adapt noting there may not be any specific regularity to these particular meetings.

In contrast, a dysfunctional team are less likely to call upon individual improvement practices, and thus, retrospectives play a more important role, providing an explicit opportunity to improve. I use the term dysfunctional in this sense to capture a broad category including newly formed teams, or simply groups of people. This does not necessarily mean the team cannot advance, nor that it hasn’t had a chance to advance, just simply the state it exists in.

Environmental Effects
I would classify a majority of environments as chaotic. In chaotic environments, improvement isn’t second nature. Through practices that start with good intentions such as auditing (“I want to have confidence you are doing what you say you are doing”), people in these environments become afraid to suggest changes, and are often fearful of attempting anything different because they’ve been punished for a failed experiment in the past. In these chaotic environments, retrospectives have a significant impact by providing an explicitly safe environment for teams to make, commit to, and hopefully be supported in making changes. Retrospectives have a higher impact in these environments because the majority of other activities doesn’t encourage learning, innovation and improvement.

In contrast, a nurturing environment welcomes fail fast innovation, rewards learning from failed experiments and supports continuous improvement in an explicit, non document centric approach. In these environments, the outcomes from implementing improvements and passing on tacit learnings is more important that meeting audits and compliance. Retrospectives have less impact in this environment because individuals are more likely to suggest and implement improvements without the need for a special meeting, and without the need for an entire team. Once again, it doesn’t necessarily imply that retrospectives are not useful (some issues require a shared understanding across the entire team) or that they are regularly scheduled events.

Avoid deciding between whether or not you run retrospectives. Consider when is it best for you to run a retrospectives instead.
Understand what situation you find yourself in using the model above and ask yourself whether or not retrospectives have the potential for the most impact (dysfunctional teams and chaotic environments), or where energy is better spent pursuing other activities because retrospectives have less, but not zero, impact (high performing teams and nurturing environments).

In the next set of posts, I hope to describe different situations I’ve seen first hand and what impact retrospectives had in relation to them.

Leave a comment and let me know what you think.

The Black Swan

My good colleague Alistair lent me a couple of books that I was finally able to get around to reading on my recent holiday. Fifteen hours travelling on a number of planes gives you plenty of time to read a book! One of the books I finished was The Black Swan. It’s been on my list of books to read so I’m glad that I finally read it.

The contents of the book are juicy, detailed and highly relevant given the state of the current economy. It’s almost a little bit too detailed to the point where I almost found it quite hard to read. The author writes using a very flowery, whimsical style, combining stories and facts to drive home the key idea to the book: Hugely significant events occur in ways that we refuse to acknowledge or be able to cope with.

His stories (sometimes false ones) create pictures and explain historical events where we try to observe data, and attempt to create models to predict the future, yet we never seem to be able to accept a completely unexpected event will eventually come along.

More importantly, he uses the book to describe how these highly improbable events having an unforeseen impact. The author chooses his words carefully to distinguish between those events where one simple random sample (e.g. people’s heights) may not affect an overall sample, but many examples in history change the game.

Experimentation and Learning lead to Ford’s production line insight

I find it slightly ironic how the learning and experimenting philosophy so heavily emphasised in the lean world ultimately produced, what is considered the opposite approach inspired by the Ford production line.

“…when Henry Ford and his team developed the production line, they didn’t just sit down and deductively theorize about it on paper. nor did they merely try random experiments. Instead, they used a bit of both. … Armed with a set of deductive hypotheses, Ford began experimenting with different configurations of his plant between 1908 and 1912. After four years of tinkering, in 1913 he struck on the key insight that the car itself should move along the production line rather than the workers…” – From Chapter 12 of the Origins of Wealth by Eric D Beinhocker.

Am I missing something?

It’s about time I probably asked this question about the new Manifesto for Software Craftsmanship, but seriously, am I missing something?

Firstly, the whole idea about craftsmanship applied to software isn’t too much of a new idea. I remember reading Software Craftsmanship: The New Imperative when it first came out, and how the Pragmatic’s also talked about this concept.

I’m probably biased a little bit because I probably believed in what craftsmanship stood for before being fully immersed in agile for the last five(?) years. A part of me understands why this is important for agilistas. After all, I hear of stories all of the time where in many organisations that focus solely on Scrum without adopting any developer discipline still have a “crappy codebase”.

Yet I worry that it focuses on the wrong problem. I worry that it may be addressing a symptom, not a cause. I worry that it will further split our industry into two camps, those who craft (or should craft) software, and everyone else.

The real question I ask myself when going into new organisations and with new teams is, “Do people care about the quality in their work?” This question applies to all parts of an organisation, all parts of a team, not just developers.

So I’m jetlagged, tired and honestly just ranting a little bit, but I still ask the question, “Am I missing something?”.

A time and place for everything

Last week at the pub, I got into a heated discussion about how to handle certain situations in retrospectives. It was a great discussion though I do wonder how other people would handle the situation. We got into the topic of dealing with safety during retrospectives, and what we can do to address safety. Someone mentioned a specific retrospective where, during the Art Gallery exercise, one person (out of a group of 25) had drawn a picture of many smiley faces and a single sad face. The Safety Check results didn’t indicate safety was a problem. The question posed was should the facilitator go ahead?

I gave a, rather rambling answer. Fair enough since it was a Friday, and well past normal working hours. Not to mention it was at the pub…

I said that, as a facilitator, you need to be constantly aware of what the situation at hand is. I explained that if I’m facilitating a meeting for someone else, particularly retrospectives, I’ll normally prepare by interviewing a few people first (informally, sometimes formally if need be). I like to know who’s going to be in the room, and what problems might surface, or what situation I might be stepping in to. I learned this tip from Kerths’ original book. I like to prepare the room before everyone enters, set up posters, whiteboards, flip charts, etc. It’s courteous to the participants, and I’m always hopeful they appreciate the effort that I made an effort, with the end result being better quality discussions. I’ll observe people as they enter, and watch the body language of people through the activities.

Given the particular example above, I can understand why the facilitator continued as they did. I often see the Art Gallery exercise used as an ice-breaker, a way of letting people have a bit of fun without being too serious. With a high safety check score, and the general mood of the group upbeat, I can understand why they proceeded.

Had many other circumstances been different, the mood of the group excessively sombre, or the safety check average versus significantly high, the outcome might be different. I talked about how, if one person out of that group had a real problem, I’d hope that there were other avenues to allow that person to express their discomfort. For example, one-to-one meetings is a great way of establishing this, or even tea and coffee breaks work with trusted co-workers does wonders. Retrospectives shouldn’t be the only place for dealing with issues.

Do you realise you’re facilitating?

A fundamental shift for people adopting agile practices is the move away from less directive management styles, to more facilitative management styles. This happens at all levels, be it the Project Manager, the Technical Lead, or simply the person arranging any meetings to order (for example, the Daily Stand Up, Retrospectives, Planning Games, etc). For those people in influential positions, I like to highlight their impact their facilitative style (good and/or bad) has on the team. Steven List is compiling a set of patterns for these, all very good and many of them which I’ve been witness to. Plenty of other books provide wonderful guides about this, like Jean Tabaka’s Collaboration Explained.

Controlling Time: Threaded Execution

Update (Feb 21): Thanks to some feedback from Taras and Lowell, the ThreadedRunner is the same as the java.util.concurrent.Executor class! I’ve updated the post to reflect this below. Thanks for the suggestion!

Unit testing threaded software can sometimes prove slightly cumbersome. Many of the examples on the net often show examples that tie a number of responsibilities together. It might be easy to see something like this:

  public class SomeExample {    
    public void doSomeWork() {
      Runnable runnable = new Runnable() {
        public void run() {
          // do some long running work
        }        
      };
      new Thread(runnable).start();
    }
  }

The thing about this class above is to realise what responsibilities it is mixing, including the new work they would like to (the item in Runnable), as well as how they would like to run it (the separate thread). It’s difficult to tease these two responsibilities apart the way it’s declared. The first thing I’d do is remove the dependency on the new thread. I’ll start by making use of the java.util.concurrent.Executor :

public interface Executor {
  void execute(Runnable runnable);
}
  
public class SingleThreadedExecutor implements Executor {
  public void execute(Runnable runnable) {
    runnable.run();
  }
}
public class NewThreadedExecutor implements Executor {
  public void execute(Runnable runnable) {
    new Thread(runnable).start();    	
  }
}

We’ll inject the SingleThreadedExecutor in our unit tests, so we only ever have one thread of execution, and we can rely on tests being consistently reproducible. We’ll inject the NewThreadedExecutor when we need to assemble our application for production. Here’s the step by step refactoring.

Wrap inside our new implementation

public class SomeExample {    
  public void doSomeWork() {
    Runnable runnable = new Runnable() {
      public void run() {
        // do some long running work
      }
    };
    new NewThreadedExecutor().start(runnable);
  }
}

Inject instance via the constructor

public class SomeExample {
  private final NewThreadedExecutor executor;
  public SomeExample(NewThreadedExecutor executor) {
    this.executor = executor;
  }  
  
  public void doSomeWork() {
    Runnable runnable = new Runnable() {
      public void run() {
        // do some long running work
      }
    };
    executor.start(runnable);
  }
}

Replace specific with interface

public class SomeExample {
  private final Executor executor;
  public SomeExample(Executor executor) {
    this.executor = executor;
  }  
  
  public void doSomeWork() {
    Runnable runnable = new Runnable() {
      public void run() {
        // do some long running work
      }
    };
    executor.start(runnable);
  }
}

In the tests, you can now inject an instance of SingleThreadedExecutor, whilst in production mode, you use the NewThreadedExecutor.

Disclaimers
Of course, this still leaves your testing strategy incomplete where you do want to test your software with the number of threads that you do expect, particularly when you need to share state across different processes.

Retrospectives are not the only place for continual improvement

Teams adopting agile, and even frequently teams who consider themselves agile, often hit a stumbling block. Here’s how the thinking goes… agile is about improvement. Agile projects do retrospective to improve. Therefore, retrospectives = improvement and improvements (only) happen in retrospectives.

Unfortunately many teams suffer without realising improvements go beyond retrospectives. Everyday there is an opportunity to improve, an opportunity to learn. It sometimes takes a while to see them. It often takes much longer to unwind the restraints of organisational “process” on people’s desires to experiment and fail fast, and learn from those mistakes.

Don’t get me wrong. Retrospectives also have their place. Sometimes teams don’t have an environment safe enough and retrospectives are one way of helping establish some safety. It takes commitment from leaders to create this environment of safety, and something I encourage greatly when I work with teams.

Do you recognise your team falling in this pattern? Break out of them, and remind them that improvements don’t have to wait for a meeting to be attempted.

What differences cause your project death?

I’m not about to go and list all the thousand differences that will contribute to a slow and painful project death, but I will mention a few categories I always see.

Differences in property names
When you start to use build files and automated builds, you will end up with property files. Often each property will be named slightly differently, especially when used, and you need to constantly remember all the different things.

Differences in test styles
Some people will prefer to put test set up in the field of a class, others that aren’t.

Differences in path locations
In one module, you might have /src/java/com, in another you might have /executable/java/com.

Differences in configuration values
I remember one project where the team had over twenty different configuration values to allow them to put parts of the codebase wherever they liked. It was a nightmare when something would go wrong, trying to track down if the difference was environmental, or if it was a true mistake.

Differences in name
Ala ubiquitous language. The users know something by one name, the BAs call it by another, the developers by yet another one. Each time, compounding the already-difficult task of communication. Don’t you think meetings are long enough without having to continuously translate terms as well as make decisions?

Differences in code style
Everything included from curly brace placement, number of spaces to naming conventions of variables. Create a code standard for those things that really don’t make a significant difference so you can spend valuable thought cycles on other things.

« Older posts Newer posts »

© 2024 patkua@work

Theme by Anders NorenUp ↑