"Elements Of Enterprise CI" Flyer

One to remember:

This flyer categorizes by levels of maturity various practices for Building, Deploying, Testing and Reporting that first appeared in our whitepaper Enterprise Continuous Integration Maturity Model. For a further description of these categories and practices please refer to the complete whitepaper.

Tags: Tools

You'll Never Be A Good Agile Developer!

Had a rather frenzied conversation with a self-proclaimed agilist this lunchtime, during which I admitted that I couldn't claim complete mastery of any particular IDE.

"You'll Never Be A Good Agile Developer!" came the immediate pronouncement.

Take that! Put me in my place!

Apparently, in the mind of this young guru, mastery of every keyboard shortcut of an editor (although which particular editor this person had in mind remained unspecified. He's a Ruby fanboy I believe, so I'm guessing that it would be something Mac-ish) was a prerequisite for agile development.

After a while, the conversation changed tack and this intense young thing-bemoaning the overall state of the I.T.world-pronounced that it would probably be better if he went back to Uni. and completed his Arts Degree.

Stepping back through the mirror, I thought it would be fun to think about all the editors that I have failed to adequately exercise over the years.

Ignoring non developer-oriented things like Microsoft Word and Adobe FrameMaker, and oddities like runoff/[nt]roff/TeX and even odder things like Literate Programming's tangle/weave I came up with this:

TOPS-20/SOS TOPS-10/TECO edlin ed/ex/vi Turbo Pascal
Turbo Prolog USCD p-System Pascal USCD p-System Modula-2 Inmos Occam Transputer Development System Macintosh/BBEdit
Macintosh/Alpha VMS/edit Think/C Apple Macintosh Programmers Workshop Metroworks Modula-2
XEmacs Project Oberon Netbeans Eclipse/MyEclipseIDE IntelliJ
VisualAge for Java JDeveloper JBuilder SunOS EditTool Visual Studio

(there are others…I'm pretty sure that the Simula 67 system I used for a while had a weird development 'environment' that I didn't really delve into; ditto for the eiffel system I used…)

Given all this, it is patently obvious that I'll never be A Good Agile Developer, but let's remember the Agile Manifesto, which states (in part):

…we have come to value:

Individuals and interactions over processes and tools…

Tags: Agile

Using PrettyTime With Groovy

TheServerSide just brought PrettyTime to my notice:

PrettyTime is an OpenSource time formatting library. Completely customizable, PrettyTime creates human readable, relative timestamps like those seen on Digg, Twitter, and Facebook. It's simple, get started "right now!"

My natural instinct was to give it a quick tryout. Of course, I used Groovy for my 'experiment':

import com.ocpsoft.pretty.time.PrettyTime

public class Test {

static void main(args) {
    def d = new Date()
    def pt = new PrettyTime(d)

    println "Now: $d"
    [-3000, -100, -1, 1, 100, 1000].each { off ->
      def nd = d + off
      println "(${nd}): ${pt.format(nd)}"
    }
  }
}

This gives:

Now: Fri Jun 19 19:28:48 EST 2009
(Mon Apr 02 19:28:48 EST 2001): 8 years ago
(Wed Mar 11 19:28:48 EST 2009): 3 months ago
(Thu Jun 18 19:28:48 EST 2009): 1 day ago
(Sat Jun 20 19:28:48 EST 2009): 1 day from now
(Sun Sep 27 19:28:48 EST 2009): 3 months from now
(Thu Mar 15 19:28:48 EST 2012): 2 years from now

Pretty rudimentary at the moment, but i18n support is coming, for instance.

Sometimes, it's little things like neat time formatting that can make the difference between users saying "great" or "gross." This may be worth keeping an eye on…

[edit]
It didn't take long before a Grails PrettyTime Plugin appeared. Pretty impressive!

Tags: Grails, Groovy, Programming

Patching Groovy With Java

"If Groovy is too slow for a particular operation, you can make use of Groovy's strong integration with Java (Groovy is Java, after all) and replace the slow Groovy implementation with one that is written in Java and which should thus be more efficient."

Every book on Groovy includes some variation of this statement…I thought I'd take a quick look and see how this can be done.

There are, of course, many alternatives…most of which rely on some degree of intrusive source code change: alter the class containing the slow method so that it extends a Java class and then remove the offending Groovy method and implement the replacement in the Java superclass; inject a Java 'helper' class and then change the slow method so that it defers to this helper; and so on.

We're talking Groovy so naturally there is a better, non-intrusive way.

Welcome to the Delegating MetaClass:

The idea is that any package.class can have a custom meta class loaded at startup time by placing it into a well known package with a well known name.

groovy.runtime.metaclass.[YOURPACKAGE].[YOURCLASS]MetaClass

In times of yore, this used to be called a tail patch and was a tool in every wild-eyed assembly-language-using coder's box of tricks. Nowadays we are much more sophisticated ;-)

Consider this simple bit of Groovy:

public class Main {
  static void main(args) {
    new Stuff().doSomething()
  }
}

And:

public class Stuff {
  def doSomething = { -> println 'Some slow Groovy stuff...' }
}

Running this trivial app gives:

Some slow Groovy stuff...

Let us assume that doSomething() turns out to be glacially slow, and moreover is a hotspot for our application. What's a boy/girl to do?

First, build a nice shiny piece of efficient Java code:

package optimized;

public class Stuff {
  public Object doSomething() {
    System.out.println ("Something efficient in Java.");
    return null;
  }
}

(there's nothing special about the package or the Class name, by the way; this just 'felt' like the best way…YMMV)

Now the Groovy Delegating MetaClass magic:

package groovy.runtime.metaclass

public class StuffMetaClass extends groovy.lang.DelegatingMetaClass {
  private final def optimized = new optimized.Stuff()

  @Override
  StuffMetaClass(MetaClass delegate) {
    super(delegate);
  }

  @Override
  public Object invokeMethod(Object a_object, String a_methodName, Object[] a_arguments) {
    (a_methodName == 'doSomething') ? optimized.doSomething() : super.invokeMethod(a_Object, a_methodName, a_arguments)
  }
}

This simple bit of code looks to see if Stuff.doSomething() is being invoked, and if so kicks off to the Java (presumably optimized) version; anything else is allowed to proceed without interference.

Note ye well: this solution is completely non-intrusive: no source had to be altered, nothing needed recompiling.

Run this, and you will see:

Something efficient in Java.

And there you have it.

This is a great way of putting temporary patches in place, or doing hit-and-run tracing of code…

I guess that there is a (not new, but still…) security concern to be aware of here too: lock up your classpath or fall foul of snooping/code injections.

And how's this for a business case: ship a 'slow' application and then dangle the "efficiency upgrade" in front of your users noses…there's no need for fancy patching toolkits, so it costs almost nothing to tell your users: "put this jar there and hey-presto your new upgrade to SuperApp++ 3000 will be complete" ;-)

Tags: Groovy, Programming

SpringSource ToolSuite 2.1 Supports Spring Batch

There's a couple of nice graphical viewer/editor modes.

This one:

Spring Batch Picture 1

And this one:

Spring Batch Picture 2

I wish I had found this out in time to incorporate it into my recent GroovyMag Article.

Better late than never, though!

Tags: Groovy, Programming, Tools

Another Book Finished

Pragmatic Thinking and Learning: Refactor Your Wetware.

This topic is not really my "sort of thing" (I generally find that these books quickly devolve into platitudes and neat little homilies). Nonetheless, I did enjoy reading it.

I found the discussion on the Dreyfuss model and Nursing, and the relevance to the software profession interesting. These paragraphs in particular resonated:

Given that the highest-skilled developers are orders of magnitude more productive than the least-skilled developers, the current common salary structures for developers is simply inadequate. Like the nursing profession years ago, we continually face the risk of losing a critical mass of expertise to management, competitors or other fields.

This tendency is made worse by the recent increases in outsourcing and offshoring development to cheaper countries. It's an unfortunate development in that it further cements the idea in people's minds that coding is just a mechanical activity and can be sent away to the lowest bidder. It doesn't quite work that way, of course.

As in the nursing profession, experts at coding must continue to code and find a meaningful and rewarding career there. Setting a pay scale and a career ladder that reflects a top coder's value to the organization is the first step toward making this a reality.

I don't know if this really reflects the main thrust of the book, but it was interesting to read.

Tags: Books

Does This Constitute Brain Damage?

Or maybe an eyesight problem?

Following on from my earlier posting giving my experiences with a USB-VGA desktop adaptor: If Two Heads Are Better Than One…

Sadly, the USB-VGA adaptor doesn't work correctly under Windows 7 (and in fact gave a blue screen crash…the first I've seen [although I have seen the NVidia driver crash and recover a few times, it never actually took anything down with it: Boo-Yah Microsoft!). Back to dual monitors for me, sigh.

Hope the manufacturer can get a Windows 7 driver available quickly, I'm feeling cramped ;-(

Interview Questions

I have been trying to make sense of this recent management fad for getting candidates to write code in the interview and/or answer "probing" questions that attempt to uncover the candidate's inner depths.

When I came across Charles Miller's posting Have you ever…, I knew that I was onto something good.

Whereas Joel Spolsky talks intently about interviewing in a way that relates to this life, Charles apparently decided to take a more otherworldly approach and use a set of questions taken from Scientology.

I'm guessing that either of these will be just as effective in determining the 'ideal' candidate…thus, I decided to check out the Scientology questions, to see what I could see.

Gems abound:

  • Have you ever trapped a thetan?
  • Have you ever practised human sacrifice?
  • Have you ever assumed a beingness which was not rightfully yours?
  • Have you ever exterminated a species?
  • Have you ever interiorized a being into a machine?
  • Have you ever forced a body to survive against its owner's wishes?

Hey! There are a few to which I could answer 'yes'; like:

  • Have you ever deliberately trained people in untruths for power, or profit?
  • Have you ever warped an educational system?
  • Have you ever tortured another with electrical, or electronic, devices?
  • Have you ever arrested the development of a culture?

(remember: I am a recovering academic!)

  • Have you ever created an effect for which there was no apparent cause?

(sure: that's what debuggers are for)

  • Have you ever poisoned an atmosphere?

(love those baked beans!)

There are some to which I answer: "I wish":

  • Have you ever prided yourself on your wickedness?
  • Have you driven anyone insane?

And think on this, when you think on me: Have you given biological bodies a bad name?

Joel's Guerrilla Interviewing; Scientology: IMHO, one (management) fad is as good as any other.

I once had to sit through a whole day of some HR drone telling me that "The Brain Is Just Like A CD Stacker."

Tags: Rant

Trivial Groovy Micro-Benchmark

Came across 5 Performance Tips for Server Side Groovy at Groovy Blogs recently.

Point #2: "Be mindful of anonymous closures." got me thinking (and then hacking)…

If this sort of thing floats your boat, consider the following:

def start = System.currentTimeMillis()
def i = 0
(1..100000000).each { i ++ }
println "Each: ${System.currentTimeMillis() - start}"

start = System.currentTimeMillis()
i = 0
for (x in 1..100000000) { i ++ }
println "For: ${System.currentTimeMillis() - start}"

In Groovy 1.6.3, using GroovyConsole, I get:

Each: 10033
For: 2973

Clearly, making all those closures for each to work with has an effect.

Is it significant? YMMV, etc. Certainly, I am glad to know about this: it's the sort of thing that can bog server-side code down. Will I avoid using each (and the other collection-oriented closures)? No way! I accept that this sort of thing is going to happen, Groovy is a dynamic language, after all. I will keep it in mind, however: Forewarned, is forearmed

I can't resist the urge to reiterate The Correct Way to approach optimization.

Tags: Groovy, Programming

Groovy With…

…surprises!

Following on from my earlier posting extolling the virtues of Groovy's 'with' closure.

This bit me a while back…

Groovy's Object.with(closure) method doesn't constitute a 'scope' and in fact global variables actually shadow the object instance ones.

Consider this script

// file: with.groovy
class X {
  def x
  def y
  def a
  def b
  }
  
static main(args) {
  def x = 99
  def y = 88
  new X(x: 42, y: 21, a: 0, b: 0).with {
    println "x: $x, y: $y, a: $a, b: $b"
    println "x: $it.x, y: $it.y, a: $it.a, b: $it.b"
    }
}

main(args)
// end with.groovy

Execution in GroovyConsole gives:

x: 99, y: 88, a: 0, b: 0
x: 42, y: 21, a: 0, b: 0

Note how on the first println $x is resolved to the global 'x', and so on.

It's not really a bug…in hindsight it makes sense (as is the way with hindsight ;-)).

It is REALLY (UNpleasantly) surprising when one comes across this issue intially, however.

The tip for novice players is: always use the with closure's parameter to access fields. Always.

Tags: Groovy, Programming