Groovy Prime Numbers

A little Groovy script to print the first 1000 prime numbers.

def t = 1..1000
def v = []

t.each { n ->
  (2..n).each { d ->
    if (n % d == 0 && n != d)
    v.add(n)
  }
}

println t - v - 1

And another version that’s more verbose but a little faster.

def t = 1..1000
def v = []

for (n = 1 ; n < 1000 ; n++) {
  for (d = 2 ; d < n ; d++) {
    if (n % d == 0 && n != d) {
      v.add(n)
      break
    }
  }
}

println t - v - 1

Scope Creep

Seven steps for avoiding scope creep

The expansion of a project outside of the planned objectives, commonly known as scope creep, is an inherent part of IT development. Scope creep can originate from several sources and is a leading cause of project failure when handled poorly. We must take measures to control project embellishment and to ensure that our teams don’t fall victim to its unsavory results – deadline delay and budget shortage.

Fortunately, there are a number of strategies one can follow to keep scope creep from derailing a project. We’ll outline these strategies in a moment. First, however, here’s a short cautionary tale that illustrates how badly things can go awry without proper planning and control.

Horror story

While working at a dot-com startup, I witnessed the scope struggles of our company during an in-house R&D effort to deliver a Web-service integration environment. This project, which began in earnest, followed no project plan and had only an uber-developer to guide its progress. It was started with a handful of very talented Java developers who had only the vision of their non-technical president to guide them.

If this sounds like a nightmare, it was and still is. It is far from a-typical, however, since most innovative visionaries struggle with feature-itis. With no formal project agreement to work from, the scope of this project changed constantly, even daily, and all efforts, from development to sales and quality assurance, became stunted by the massive workload a changing vision created.

On the bright side

The effects of scope creep are not always negative, depending on your situation. If you work as a consultant or for a consulting firm, “feature-itis” can be great for business, as long as it’s handled professionally. For in-house software development, additional features could give your product the edge over your competition. But that edge is lost if you release a month or two late. Regardless of the perceived effects of scope creep, cost is always the bottom line, and that’s not just dollars, it’s also team moral and time to market. By controlling your cost of development and by delivering on time, your project can be a success, without compromising flexibility in production.

Scope control starts on day one

Controlling the scope of your project begins before the first line of code is written. Every development effort should have a corresponding project plan or project agreement, regardless of the situation. Even if you’re just one developer trying to make the boss happy, you’ll benefit greatly from documenting your efforts before you begin them. Use the following guidelines to set yourself up to successfully control the scope of your project:

  1. Be sure you thoroughly understand the project vision. Meet with the project drivers and deliver an overview of the project as a whole for their review and comments.
  2. Understand your priorities and the priorities of the project drivers. Make an ordered list for your review throughout the project duration. Items should include budget, deadline, feature delivery, customer satisfaction, and employee satisfaction. You’ll use this list to justify your scheduling decisions once the project has commenced.
  3. Define your deliverables and have them approved by the project drivers. Deliverables should be general descriptions of functionality to be completed during the project. Ideally your deliverables are described as a suite of functional tests.
  4. Break the approved deliverables into actual work requirements. The requirements should be as detailed as necessary and can be completed using a simple spreadsheet. The larger your project, the more detail you should include. If your project spans more than a month or two, don’t forget to include time for software upgrades during development and always include time for automated testing – lots of it.
  5. Break the project down into major and minor milestones and complete a generous project schedule to be approved by the project drivers. Minor milestones should not span more than a month. Whatever your method for determining task duration, leave room for error. When working with an unknown staff, I generally schedule 140 to 160 percent of the duration as expected to be delivered. If your schedule is tight, reevaluate your deliverables weekly. Coming in under budget and ahead of schedule leaves room for additional enhancements.
  6. Once a schedule has been created, assign resources and determine your critical path using a PERT Chart or Work Breakdown Structure. Microsoft Project will create this for you. Your critical path will change over the course of your project, so it’s important to evaluate it before and during development. Follow this map to determine which deliverables must be completed on time. In very large projects, I try not to define my phase specifics too early, but even a general plan will give you the backbone you need for successful delivery.
  7. Expect that there will be scope creep. Implement Change Order forms early and educate the project drivers on your processes. A Change Order form will allow you to perform a cost-benefit analysis before scheduling (yes, I said scheduling) changes requested by the project drivers.

If you can perform all of these steps immediately, great. However, even if you start with just a few, any that you’re able to implement will bring you that much closer to avoiding and controlling scope creep. That way, you are in a better position to control your project, instead of your project controlling you.

Java Tips

Using MessageFormat to control the formatting of variables

MessageFormat allows a developer to control the formatting of variables in output text. It is a powerful class, as the following example shows.

String message =
 "A while ago ({1,date}, around about {1,time,short}), there " +
 "was a humble developer named Geppetto who slaved for " +
 "{0,number,integer} days with {2,number,percent} complete user " +
 "requirements.";

Object[ ] variables =
 new Object[ ] { new Integer(4), new Date( ), new Double(0.21) }

String output = MessageFormat.format( message, variables );

Hidden in the message is a little language that describes the formatting of the output. An example value for ‘output’ is shown below:

A while ago (Nov 3, 2002, around about 1:35 AM), there was a humble
developer named Geppetto who slaved for 4 days with 21% complete user requirements.

If the same message needs to be pushed out again and again with different variables, then a MessageFormat object can be built and given the message. Here’s a modification of the above example:

//    String output = MessageFormat.format( message, variables );
//    becomes:

      MessageFormat formatter = new MessageFormat(message);
      String output = formatter.format(variables);

Using recursion to delete a directory structure

static public void deleteDirectory(File dir) throws IOException {

  if( (dir == null) || !dir.isDirectory) {
    throw new IllegalArgumentException(
      "Argument "+dir+" is not a directory." );
  }

  File[ ] entries = dir.listFiles( );
  int sz = entries.length;

  for(int i=0; i < sz; i++) {
    if(entries[i].isDirectory()) {
        deleteDirectory(entries[i]);
    } else {
        entries[i].delete();
    }
  }
  dir.delete();
}

Converting objects to byte arrays

static private byte[] object2Bytes(Object o) throws IOException
{
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  ObjectOutputStream oos = new ObjectOutputStream(baos);
  oos.writeObject(o);
  return baos.toByteArray();
}

Converting byte arrays to objects

static private Object bytes2Object(byte raw[]) throws IOException, ClassNotFoundException
{
  ByteArrayInputStream bais = new ByteArrayInputStream(raw);
  ObjectInputStream ois = new ObjectInputStream(bais);
  Object o = ois.readObject();
  return o;
}