Tuesday, 15 March 2011

Agile software development recommendations for users and new adopters

Let me begin by saying that I am an agile believer and as a team player I enjoy this methodology much more than the traditional waterfall methods.

Agile is like a fashion these days. Its one of the buzz words, it's "cool"...and I think it actually is.
With popularity also comes rumors, myths and misunderstandings that often cause problems in agile projects and blames attributed to the process itself.

There are many teams claiming to use agile without even knowing the manifesto.

Yes, it is not be the answer to all software development problems, one size doesn't fit all, but before you adopt it in your project or blame it for not working please read this and if you have some feedback feel free to leave a comment!

If you are considering agile take into account

  1. Project size.
    It's easy to apply agile in a new project, relatively small ( tens $K), with traditional client-server architecture and clearly defined users/customers but ..
    what about a re-write of an existing big project (hundreds or millions $) with distributed software and multiple stakeholders? Is hard to deal with that in agile methodologies...check this article for more info.
  2. Customer or product owner must be agile
    If all your customer really wants is a product with a fixed number of features in a fixed time frame, then you are probably going to fail. You are anyway even if you don't use agile. But I guess the point is agile is not going to help.
    In agile you have to continuously redefine the requirements, re-elaborate them, re-prioritize them. Your customer must know and accept that.
  3. Your organization must be agile
    No point going for an iteration based model if your company still requires all work to be signed-off in an upfront specification. To get the right value you need to be able to adapt ongoing work as it progresses.
  4. Your team might not be ready
    Yes, that's right the team might not be mature enough to be self-managing  and it is one of the points in the agile manifesto. You need to realize if you are going to start agile and lead accordingly. (Very good article here)
    You might have to hold on and train / lead your team ( and yourself ) for some more time.
    Agile approaches require a mentality shift. Simple things like saying something is "DONE" means is  production ready. It doesn't mean the code is done and now somebody else will have to make sure it works. Your team needs to be mature enough to own and  understand what they are committing to.
  5. Agile does NOT mean you are going to develop your software faster.
    That must be clear to all project managers.
    It increases business value and ROI because using agile the team focus on features that are prioritized by business value and incrementally deliver working software at regular interval.
    Less features => faster
    If you just consider the total time, agile is going to take longer due to continuous code refactor
  6. Don't do it just for the sake of it
    Embrace agile only if you believe in it. Not because people say it works.
    Or even worse just to tell your customers you are an 'agile' company.
    There are lots of successful company that never used it. 

If you are already using agile then

  1. Make sure you have a clear and commonly accepted definition of DONE.
    The whole team needs to understand the process. Make sure they are aware, understand and accept that. Your sprint artifacts must be production ready.
    Also remember that if your sprint outcome is not actually being deployed to production (for whatever reason) you are bending contract. Just take it into account that "production" bugs might be lurking in your code.
  2. Watch the technical debt
    Very often the technical debt tends to build up over the sprints due to. You need to closely monitor it and allocated time during your sprints to skim it off.
  3. Don't let team members act as product owner
    The product owner is the most important player. Is the one telling you want to do but most of all what to do first. The right prioritization of user stories will determine the success or failure of the project and only the owner should do it.
    Sometimes if you have a large team, you might be tempted to have someone in your team (most likely the BA) wear the product owner's hat.
    That can lead to a lot of problems and misunderstandings. One of the key points of the agile manifesto is "Customer collaboration over contract negotiation". 
  4. Your team is likely to be diverseNot every team member can take every story. Someone says agile is not junior developer friendly. Well its a bit more than that. You might have different people specialized in different disciplines and that will create a lot of contention / dependencies that you need to deal with.
  5. Spend appropriate time on your automation and continuous integration
    Part of the agile process is to continuously build and integrate the software. Developers are meant to run tests all day long.
    If your build takes 30 mins, your application server needs another 5 and so on then your productivity is really going to suffer. Spend some time to break off the application in smaller more maintainable pieces.
    Don't drag along cause together with the productivity the team is going to run into the bad habit of not running or skipping the procedure.
  6. Go for the "simplest possible" but don't forget the design principles
    The idea here is to get feedback as soon as possible. So if your application is going to going to generate graphs, there is nothing wrong in having an excel based first version to be sure you understand what the customer wants.
    What you need to be careful is that software architecture and design principles are not left out!
  7. Don't forget non-functional requirements
    User stories only talk about required function. The critical “how well” attributes are totally absent. Your stakeholders will expect them anyhow and that is when you are going to get in trouble.
    All the things like performance, scalability are really making the difference these days.  Check why chrome is becoming more and more popular

Thanks for reading this, your feedback is welcome!

Tuesday, 8 March 2011

Testing your Play! controllers

Lets say you have a controller like this (from the Play! documentation)

package controllers;
 
import java.util.*;
 
import play.*;
import play.mvc.*;
 
import models.*;
 
public class Application extends Controller {
 
    public static void index() {
        Post frontPost = Post.find("order by postedAt desc").first();
        List olderPosts = Post.find(
            "order by postedAt desc"
        ).from(1).fetch(10);
        render(frontPost, olderPosts);
    }
 
}

And you want to write a test to check the render parameters are correct, how do you do that?

Well here is a little example
public class ApplicationTest extends FunctionalTest{
 @Before
 public void before() {
  Fixtures.deleteAllModels();
  Fixtures.load("data.yml");
 }

 @Test
 public void testHomePageFirstPost() throws MalformedURLException {
  // Call the home page
  Response response = GET("/");
  
  // Verify that Matches.matchCreate() passed correct params to render().
  Post frontPost = (Post) getRenderParameter("frontPost");
  assertEquals(${value_from_yml}, frontPost.author.fullname);
  assertEquals(${value_from_yml}, frontPost.postedAt);
 }

 /**
  * Gets the parameter that was passed to render() method.
  * @param key
  * @return
  */
 public static Object getRenderParameter(String key) {
  RenderArgs current = Scope.RenderArgs.current();
  return current.data.get(key);
 }

}

You might want to put the getRenderParameter in a separate class to easily reuse it.


If you want to test a controller method that take parameters is as easy.

Let's assume you want to test a simple controller method in Users called getUserByUsername to make sure the correct user is added to render when the form is submitted

public class Users extends Controller {
 
 /**
 * Gets the user given his username
 */
    public static void getUserByUsername(String username) {
        Assert.notNull(user);
        User currentUser = User.find("byUsername", username).first();
        render(currentUser);
    }
 
}



In this case the test would be

public class UserLoginTest extends FunctionalTest{

 @Before
 public void before() {
  Fixtures.deleteAllModels();
  Fixtures.load("users.yml");
 }
 
 @Test
 public void testGetByUsername() {
  Map<String, String> params = new HashMap<String, String>();
  params.put("username", "user1");
  Response response = POST("/users/getbyusername", params, new HashMap<String, File>());
  User currentUser = (User) getRenderParameter(&quot;currentUser&quot;);
  assertEquals(${from_users.yml}, currentUser.name);
  assertEquals(${from_users.yml}, currentUser.email);
 }
}


Please feel free to comment!

Thanks

Saturday, 5 March 2011

Run tasks in parallel and set your own time out

Many times blocking method calls might cause problems in your applications.
If the code is waiting for some resource availablity and you cannot specify a timeout option...well you're stuck!

You might have seen this with javax.jms.Connection, you try to open a connection when the network is down and your application freezes. No exceptions or anything telling you what's wrong.

Using the the java.util.concurrent api you can run the problematic code in a separate thread and wait for the completion or timeout of this execution.

Here is some code calling a jms connection factory in a separate thread.

private Connection getConnection() throws NamingException, JMSException {
 FutureTask<Connection> createConnectionTask = null;
 try {
  createConnectionTask = new FutureTask<Connection>(new Callable<Connection>() {
   @Override
   public Connection call() throws Exception {
    logger.debug("Calling connection on the connection factory");
    Connection connection = (Connection) connectionFactory.createConnection();
    return connection;
   }
  });
  // start task in a new thread
  new Thread(createConnectionTask).start();

  logger.debug(String.format("Wait for the execution of createConnection to finish, timeout after %d ms", CONNECTION_TIME_OUT));
  connection = createConnectionTask.get(CONNECTION_TIME_OUT, TimeUnit.MILLISECONDS);
 } catch (TimeoutException e) {
  JMSException jmsException = new JMSException(e.getMessage());
  jmsException.setLinkedException(e);
  throw jmsException;
 } 
 return connection;
}


The main thread will create a java.util.concurrent.FutureTask that returns the connection you need.
It'll wait a maximum of CONNECTION_TIME_OUT milliseconds before throwing a TimeoutException. This way you can have complete control of your code execution!

Friday, 4 March 2011

Reuse your test code in maven projects!

Here is a quick tip if you are using maven.
If you create some test utility or simply want to reuse some test class in a different project you don't need to duplicate the code or put the code in the main section, just do this:

In the project you have code to share add this section to you pom.xml
<build>
 <plugins>
  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-jar-plugin</artifactId>
   <version>2.2</version>
   <executions>
    <execution>
     <goals>
      <goal>test-jar</goal>
     </goals>
    </execution>
   </executions>
  </plugin>
 </plugins>
</build>

and in the using project you want to use the test utilities add this

<project>
...
 <dependencies>
  <dependency>
   <groupId>com.myco.app</groupId>
   <artifactId>foo</artifactId>
   <version>1.0-SNAPSHOT</version>
   <classifier>tests</classifier>
   <scope>test</scope>
  </dependency>
 </dependencies>
...
</project>