18 January 2011

2011 Course Planning

Whew! Looks like March is going to be a busy month. I've planned no less than 3 courses back to back, so hard work ahead...

I'll be kicking off with the 5-day "Intro to Java" course on 7-11 March. It seems like Cape Town's demand for Java developers is insatiable. I've had requests from a couple of clients for this course simply because they just can't find good Java devs for their expanding teams, and they're going to be hiring developers with good OO experience from other (non-Java) environments and training them up for Java development as an alternative. Now, I know that any good developers loves learning new stuff, so I think these clients are doing a Good Thing by offering skills-development as part of their hiring process. My job is to give them the best possible Java Platform course, and I have great plans for delivering just that!

Next up will be the newly developed 5-day "Web Application Development with Servlets and JSP". If you've last looked at JSP technology a few years ago, possibly run away in terror at the sight of all the horrible in-page logic that made scriptlet-based JSPs such a nightmare for maintenance, then you really owe it to yourself to get up to speed with scriptlet-free, tag-based JSP development. The course includes topics on the new, new Servlet-3.0/JSP-2.2 enhancements that use annotation-based configuration.

And last, but not least, will be my much-acclaimed 4-day "OO Analysis and Design" course – thus fitting neatly into the 4 working days that remain after the Human Rights Day public-holiday.

I'm planning to run all the courses in Cape Town. (still looking for a great venue, so please drop me a line of you know of something extraordinary.)

Drop me a line if you're interested in any of these. Miss this opportunity at your own risk – I will probably not be scheduling courses in Cape Town again before August!

I'm offering an Early Bird discount of 20% to anybody who confirms a reservation before the end of January!

07 December 2010

Amazon Route 53: Trustworthy?

As a "user" of Amazon's Web Services (I've kicked the tyres on S3, but not much more than that) I received an email from Amazon punting their new DNS service, dubbed "Amazon Route 53".

I wonder though, in the wake of their termination of WikiLeaks, whether I would trust any part of my DNS infrastructure to Amazon. Suppose I did something to piss off the US governement - hosted a DNS entry for WikiLeaks, perhaps? at, say, http://wikileaks.mikro2nd.net/ - and some US government official notices (pretty unlikely, I know, but...) and whispers into Amazon's ear, would I, too, lose use of this critical infrastructure without review, recourse or refund?

So, no! I don't think I'll be using Amazon Route 53 much...

18 October 2010

HTTP Response codes & msgs as Java enum

Just in case it saves someone else the tedious typing... Capitalisation of messages duplicates the inconsistencies in RFC2616. Don't ask me...

    public enum HttpResponse {
        HTTP_100( 100, "HTTP/1.0 100 Continue\r\n\r\n" ),
        HTTP_101( 101, "HTTP/1.0 101 Switching Protocols\r\n\r\n" ),
        HTTP_200( 200, "HTTP/1.0 200 OK\r\n\r\n" ),
        HTTP_201( 201, "HTTP/1.0 201 Created\r\n\r\n" ),
        HTTP_202( 202, "HTTP/1.0 202 Accepted\r\n\r\n" ),
        HTTP_203( 203, "HTTP/1.0 203 Non-Authoritative Information\r\n\r\n" ),
        HTTP_204( 204, "HTTP/1.0 204 No Content\r\n\r\n" ),
        HTTP_205( 205, "HTTP/1.0 205 Reset Content\r\n\r\n" ),
        HTTP_206( 206, "HTTP/1.0 206 Partial Content\r\n\r\n" ),
        HTTP_300( 300, "HTTP/1.0 300 Multiple Choices\r\n\r\n" ),
        HTTP_301( 301, "HTTP/1.0 301 Moved Permanently\r\n\r\n" ),
        HTTP_302( 302, "HTTP/1.0 302 Found\r\n\r\n" ),
        HTTP_303( 303, "HTTP/1.0 303 See Other\r\n\r\n" ),
        HTTP_304( 304, "HTTP/1.0 304 Not Modified\r\n\r\n" ),
        HTTP_305( 305, "HTTP/1.0 305 Use Proxy\r\n\r\n" ),
        HTTP_307( 307, "HTTP/1.0 307 Temporary Redirect\r\n\r\n" ),
        HTTP_400( 400, "HTTP/1.0 400 Bad Request\r\n\r\n" ),
        HTTP_401( 401, "HTTP/1.0 401 Unauthorized\r\n\r\n" ),
        HTTP_402( 402, "HTTP/1.0 402 Payment Required\r\n\r\n" ),
        HTTP_403( 403, "HTTP/1.0 403 Forbidden\r\n\r\n" ),
        HTTP_404( 404, "HTTP/1.0 404 Not Found\r\n\r\n" ),
        HTTP_405( 405, "HTTP/1.0 405 Method Not Allowed\r\n\r\n" ),
        HTTP_406( 406, "HTTP/1.0 406 Not Acceptable\r\n\r\n" ),
        HTTP_407( 407, "HTTP/1.0 407 Proxy Authentication Required\r\n\r\n" ),
        HTTP_408( 408, "HTTP/1.0 408 Request Time-out\r\n\r\n" ),
        HTTP_409( 409, "HTTP/1.0 409 Conflict\r\n\r\n" ),
        HTTP_410( 410, "HTTP/1.0 410 Gone\r\n\r\n" ),
        HTTP_411( 411, "HTTP/1.0 411 Length Required\r\n\r\n" ),
        HTTP_412( 412, "HTTP/1.0 412 Precondition Failed\r\n\r\n" ),
        HTTP_413( 413, "HTTP/1.0 413 Request Entity Too Large\r\n\r\n" ),
        HTTP_414( 414, "HTTP/1.0 414 Request-URI Too Large\r\n\r\n" ),
        HTTP_415( 415, "HTTP/1.0 415 Unsupported Media Type\r\n\r\n" ),
        HTTP_416( 416, "HTTP/1.0 416 Requested range not satisfiable\r\n\r\n" ),
        HTTP_417( 417, "HTTP/1.0 417 Expectation Failed\r\n\r\n" ),
        HTTP_500( 500, "HTTP/1.0 500 Internal Server Error\r\n\r\n" ),
        HTTP_501( 501, "HTTP/1.0 501 Not Implemented\r\n\r\n" ),
        HTTP_502( 502, "HTTP/1.0 502 Bad Gateway\r\n\r\n" ),
        HTTP_503( 503, "HTTP/1.0 503 Service Unavailable\r\n\r\n" ),
        HTTP_504( 504, "HTTP/1.0 504 Gateway Time-out\r\n\r\n" ),
        HTTP_505( 505, "HTTP/1.0 505 HTTP Version not supported\r\n\r\n" );

        private final int intValue;
        private final String msg;

        private HttpResponse( int intValue, final String msg ){
            this.intValue = intValue;
            this.msg = msg;
        }

        public int intValue(){
            return intValue;
        }

        public String responseString(){
            return msg;
        }

        public static HttpResponse forResponseCode( int responseCode ){
            for( HttpResponse v : values() ){
                if( responseCode == v.intValue() ) return v;
            }
            throw new IllegalArgumentException();
        }
    }

13 October 2010

A Lesson from Vegetable Gardening for Hiring (and Keeping) Better Software Developers

Right now I'm in the midst of Busy Season in the Veggie Garden: Spring Planting Time. Even busier than harvest time. You see, you can almost always delay a harvest by a few days or a week without serious consequences. But you can't delay sowing seed without reaping serious consequences 4 to 6 months down the line. Veggie gardening is all about strategy.

Just the other day I heard about a successful and growing Cape Town company planning a hiring spree for Java developers. They'll be looking for quite a number of Java developers at all skill and experience levels.

But they face two key problems:
  1. There is an extreme scarcity of Java developers at any and all levels in Cape Town and surrounds.
  2. They'll be competing against a very large number of other employers looking for large numbers of Java developers. I have, over the past couple of months, heard of numerous companies searching for 10, 12 and more "skilled Java developers".
If you're in Cape Town you can probably take a reasonably accurate guess as to who those companies are. And they're not finding any developers, are they. Let alone really excellent developers...

This is great news for Java devs: Salaries are pretty competitive, even if not quite up to Jo'burg levels just yet.

Hell for employers, though.

Strategy is about Time

My main problem this Planting Season is that I don't have any compost for the garden. The key to making great compost is adding plenty of water, and the key to great veggie crops is building the soil by adding compost, year after year after year. But we're (still) in a drought, so no water. Successful crops are going to be a serious challenge this Summer...

CEOs, CTOs and Development Managers who get it know that investing in their developers' skills, knowledge and experience is investing in their own success and the success of their business. And the secret is that it can't be done overnight. It takes long-term commitment to helping their developers build their skills. And intelligent developers reward real, honest commitment to skills- and career-development with loyalty.

And developers talk to each other. In their mailing lists and user-group meetings, on Facebook and Twitter, word-of-mouth ensures that developers have a pretty good idea of who is doing the interesting software, who is providing a stimulating development environment. In short, who the good employers are. (Especially in Cape Town! The software world in CT really is a very small village.)

Compost making and soil-building is a strategic practise for farmers and gardeners everywhere, whether they are organic growers (like me) or not, soil-building is of vital strategic importance. Without healthy soil we have nothing.

Likewise, CEOs, CTOs and Dev Managers of companies for whom software development is a strategic business activity have a vital interest in developing their developers.

Planning to Hire Developers Any Time Soon?

If you are planning to attempt to hire developers (particularly Java developers; particularly in or around Cape Town) within the next 6 months, ask yourself the following 3 questions:
  1. How are you going to source the best and brightest devs when they're almost unreachable at any price?
  2. How are you going to make your company more attractive to those devs than all the competition you face?
  3. How are you going to keep developers from job-hopping when they get that email from a competing employer or headhunter offering them a huge raise?
If you have good answers to all of those, then please don't call me!

If you'd like help creating fertile ground for interesting minds who can help drive your software development to greater successes, call me.


05 October 2010

Duck Typing Developer Styles: 4 Ducks

Developers can be categorised along two orthogonal dimensions: coding-skills and design-skills. This post explains how to locate a developer according to this scheme, and describes how best to manage each development-style.


Tame Ducks are easy to manage, get on with the job, etc. They produce decent working code, but won't come up with the most innovative solutions. Great maintenance coders.

Wild Ducks are your innovators who will break new ground, but it's hard to get them to follow rules, comply with standards, etc. Give them the tough stuff to code.

Lame Ducks: deal with a Lame Duck by making Duck Sandwich. Sandwich the Lame Duck between a Wild Duck and a Tame Duck. They will either learn and gain competence, so becoming a Tame Duck in time, or they will Ship Out through fear of revealing their lack of knowledge.

QUACKS: talk a good project; strong tendency to bullshit their way through design by resorting to TLAs like SOA. XML and xDD. Deal with them by - again - making Duck Sandwich. The Wild Duck has exquisitely sensitive bullshit-detection capacity which, combined with their cultivated lack of tact and intolerance for freeloaders, will leave the Quack with no place to hide. The Tame Duck is there to back up the Wild Duck's assertions as to the Quack's actual performance. The Quack will almost certainly soon move on.

(Where do I fit in? ;-)

Credit: I first heard this Duck-Typing Scheme from an important mentor in my career, Nat Lunn, sometime around 1990, and so I must credit the whole story to him. Thanks, Nat!

13 September 2010

Setting up a PPTP VPN with KDE NetworkManager

Filed under "Notes to Myself". If this helps someone else out there, Good!

The problem: to VPN into a closed Microsoft-dominated network.

After 6 weeks of hacking at it, the client's network administrator finally managed to get the VPN set up on their office server (some version of Windows is involved, so no wonder it is an opaque and difficult process taking weeks and involving numerous reboots. I am frequently moved to wonder whether people actually enjoy the pain that results from using Microsoft software... I can't think of any other reason to use it.)

So it helps to have the admin tell you:
  • the gateway address for the VPN
  • your username and password
More importantly for a n00b to VPNs (i.e. me) it help to get told that
  • the VPN protocol is PPTP (MS proprietary AFAICT) and
  • that it requires some (MS peculiar) encrytion scheme (MPPE) to be used.
Surprise, surprise! Only took a day to figure these things out.

The rest of the trouble comes from Kubuntu Linux insisting on using the fucked-up awful NetworkManager. I could not find reliable/working information on setting up the correct config by hand, so was forced to rely on NM. Also tried Kvpnc, but could not make it work for the client network configuration.

NM insists on setting the default route for all network traffic to be via the VPN client network. Not what I want. I need on-going access to my own local network resources as well as the VPN resources (as well as my own internet connection) as I am developing stuff that relies on local resources to work. After starting the VPN, my machine's routing table looks like

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
41.133.194.199  192.168.1.254   255.255.255.255 UGH   0      0        0 eth0
41.133.194.199  192.168.1.254   255.255.255.255 UGH   0      0        0 eth0
192.168.0.23    0.0.0.0         255.255.255.255 UH    0      0        0 ppp0
192.168.1.0     0.0.0.0         255.255.255.0   U     1      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0
0.0.0.0         0.0.0.0         0.0.0.0         U     0      0        0 ppp0
(192.168.1.0/24 is my own local net; 192.168.0.0/24 is the client's network.)

Note that last line. There's the troublemaker. I don't want all traffic routed to the VPN by default. I tried every possible combination of settings in the KNetworkManager applet, especially those that claim to prevent the VPN from overriding the automatic routing. I tried manually setting all the VPN info (IP address, netmasks, etc.) but that fails to work either.

Ultimately I resorted to a workaround. Accept the crappy routing that NM sets up for me, then fiddle with the routing tables by hand:
$ sudo route del -net 0.0.0.0 ppp0
$ sudo route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.1.254 dev eth0
These 2 lines get me a sensible default route outta here, and
$ sudo route add -net 192.168.0.0 netmask 255.255.255.0 dev ppp0
gets me a route to all the client-network resources (albeit without any DNS lookups for their subdomain; this I can live without, since there are only a small handful of machines I need access to.)

The resulting routing table:
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
41.133.194.199  192.168.1.254   255.255.255.255 UGH   0      0        0 eth0
41.133.194.199  192.168.1.254   255.255.255.255 UGH   0      0        0 eth0
192.168.0.23    0.0.0.0         255.255.255.255 UH    0      0        0 ppp0
192.168.1.0     0.0.0.0         255.255.255.0   U     1      0        0 eth0
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0        0 ppp0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0
0.0.0.0         192.168.1.254   0.0.0.0         UG    0      0        0 eth0

Can't say it's pretty, but it works.

03 August 2010

Measuring Progress in Software Development

Background

I am about to take on the leadership of a new, still-in-formation developer team, on a project - the first of several - of critical importance to the client. This means that everything is up for negotiation: team structure, development methodology, coding styles, frameworks to be used,... everything!

Initially my role was confined to that of Consulting Architect, but, by force of circumstance, has evolved to Architect and Team Leader pro tem for a few months while the client gets their dev team properly resourced and settled-in. Naturally I'm trying to help that along as best I can.

Methodology

The client initially planned to use a BDUF (Big Design Up Front), waterfall approach to the project. The requirement is extremely well-known and quantified, in a very well understood business domain.

I have never believed in my tummy that BDUF is in any sense realistically or practically achievable, though, even long before the Agile Movement tore the idea to shreds. It is impossible to foresee every detailed design element, no matter how hard you work at it. On the other hand, some Agile proponents seem to say that no up-front design is necessary... Perhaps my hearing is playing tricks with me. I cannot agree with them, either.

So call me a proponent of SDUF: Some Design Up Front.

And on the Process front, I don't think there's a lot to argue about when we contrast a waterfall/sequential process with an agile/incremental process. For me the critical difference lies in how we report and feed-back progress and how frequently we do this. And what we do about the feedback we receive - how flexibly we accommodate direction changes from customers, business sponsors, unit-tests,... to change the still-in-the-pipeline development and requirements without completely trashing the budget and time-to-market constraints. An also-essential aspect of agile development is "to reflect on what has gone before, and to adjust what we do to make
things better." [Ron Jeffries]

Waterfall possibly still does have a place in some circumstances. I can't honestly say that I've ever actually been party to such circumstances, though I've certainly been on projects where some of our business partners thought they needed hard, contractual milestones with no going back. (In reality we always "went back" anyway, when necessary, after some amount of renegotiation.)

Metrics

A very greenfield situation, this, which some people would immediately call a "wonderful opportunity", but which I very much see as a "two-edged weapon"...

The question that has been most on my mind is, "What should we measure?"

I am a very firm believer in the old saw, "Tell me how you Measure me, and I'll tell you how I Behave."

Measure a sales-person by the number of sales, and you'll get a high order volume of the easiest-to-sell products, regardless of whether they represent the best margins or quality-of-business for the company. Measure the same sales-person by margin-value of product, and you'd best hope that your high-margin products are ones that lots of people want to buy. Measure them by the number of sales calls they make and you'll have lots of calls that don't result in sales.

Here is where I believe that some Scrum proponents are going wrong... We take Features and break them up into Tasks - the developers' unit-of-work. And they measure Task completions using a burn-down chart of Tasks completed versus time. This can easily result in a situation where many Tasks are being completed, but not so many Features. A situation where Features reach an 80%-complete state, and then get stuck, for any of a variety of reasons, all of which amount to "Nobody wants to complete those Tasks" because they're boring,... or they're "just" test Tasks,... or they're difficult (because not well understood), or...

The solution is really simple. Just measure Feature completion instead of Task completion. Then the team only gets rewarded when Features or User Stories get completed. We only get beer and Pizza when the Business gets value.

But is this enough? Can we go further? Is there a way to tie developer reward directly to delivered Business Value?

In the situation I'm headed into, Business Value should be pretty easy to quantify: The product to be built is one that will directly generate revenue for the company, so we can very easily quantify how much Business Value the software is generating. (Successful completion of the product will also deliver a huge  strategic Business Value by enabling new revenue streams, but that's also quite easy to quantify, and, indeed, is the prime reason the client is taking on this quite substantial investment in the first place...)

Are there ways to close the loop? To feed-back to the dev team on how much business-value their efforts are generating without making money too much of an up-front issue? Then, too, I have a reservation: Developers can have notoriously short memories, and the sort of value we're talking about here is only delivered on longer time-scales... Maybe it's good to have both long-time-loop feedbacks as long as we also have the short-timespan feedback in place as well... Waterfall's failures are largely a result of too little feedback taking too much time for us to correct project course when we need to.

My instinct is that moving towards a continuous deployment process (the step beyond continuous integration) might help to shorten this feedback loop, which is completely the point of "agile" thinking, but I'm still not really clear on how we might implement it.
Related Posts Plugin for WordPress, Blogger...