« January 2006 | Main | March 2006 »

February 28, 2006

Active Learning

When you're on one of our courses, you're trying things out along with the tutor, you're watching him write programs that include data that you provide in class, and you're interacting with questions and answers all along. I call it active learning and it's very VERY effective.

"It was very interesting to see how long my attention was permanently kept up" wrote a delegate on last week's Perl course in a follow up email to me over the weekend.

With about half a dozen delegates on a course (we won't take more than 7 on a public course), we can ensure an active and effective learning experience for every attendee - sitting in the back and getting lost is NOT an option at Well House Consultants. That's probably why everyone tells their friends about us and we're looking busy for months ahead.

"thanks for the excellent teaching of a really good course" concluded my email from my Perl delegate.

Posted by gje at 06:58 AM

More about Graham Ellis of Well House Consultants

February 27, 2006

JIT or JAU

Are you a "Just in time" person or a "Just after use" person? I do my best work / preparation shortly before it's due, and I'll admit to rushing around this morning getting everything in place for the MySQL course that starts - err - shortly.

We have plenty of resources / backup, and I do take care to ensure that the more humble jobs that we all have to muck in with (loo, fag ends, etc) are done before the first customer knocks on the door.

Systems up and running check
Loos clean check
Coffee machine serviced check
Paperwork tidied away check
Blog written check !
and so for the course; another fabulous day in Melksham. Really looking forward to this one - nice sized group, single application, fresh to SQL ...

Posted by gje at 08:45 AM

February 26, 2006

Not just a pretty face to answer the phone.

Many years ago when I was the UK's technical expert on range of computer graphics products, one of my sales and marketing colleagues had me return a call to a gentleman who was "Technical Director" of a small but high tech company in Cambridge.

Alas, my Technical Director wasn't available, but the lady who answered the phone asked me if she could help and - hey - why not tell her the reason for my call. She turned out to be knowledgeable - VERY knowledgeable - about the project I had called to discuss and how the company wished to use our computer graphics terminals, and I felt that my job was done. Being mindful, however, that messages can get lost as they're passed around I felt I should make a note of who I was talking to. "In case I speak with John Smith in the future and need to refer back to this conversation, who am I speaking to?" I asked. "Juliet Blackburn". "And what is your role with xxxxxx". "I'm the Managing Director" she replied.

I was reminded of this story as I was going through my weekend mailbox, having spend an exhausting week visiting every country except Wales in the British Isles, and I came to an email that started "I spoke to the receptionist who said that you were not available ....".

That's funny - we don't have a receptionist. This must be the guy who spoke with Lisa - and wouldn't tell her what it was about. Oddly enough, the question that he goes on to ask is one that Lisa could have answered for him just as well on Friday (if not better) than I can. Now I'm certain that Lisa asked if she could help the gent ... in fact, she's quite put out when people make an assumption that she can't help because she happens to be on phone duty and she had actually emailed me about this particular call to give me a "heads up".

It remains our target to have a knowledgeable team here so that anyone who phones or emails us can get a prompt, courteous and correct answer within a couple of hours - at least to the extent of having triaged requests. And yet we all get those calls from time to time where the caller refuses to speak with us if we pick the phone up, insisting on being put through to someone who can help. Of course, we do try not to say anything awkward when the call is passed back again a minute or two later.

Posted by gje at 12:48 PM

February pictures

Even in February, there's some beautiful scenery around. Three pictures from yesterday.


Killingworth Lake, Lake District, at dawn



Crickley Hill, Gloucestershire, late morning



Swainswick Wood, near Bath, mid afternoon

Posted by gje at 08:15 AM

It's REALLY easy to add a little PHP

I've taken to describing PHP and an "HTML++" language when I'm training. That's to show absolute newcomers to PHP that they can simple write a page of HTML, give it an extension such as .php, and it will function in exactly the way it always has for them.

Then, very gently, the newcomer can add in some extra tags - the "++" that I talk about in the "HTML++" of the language. These extra tags are recognised by the web server, so there's nothing at all special required by the user's browser.

I've put a demonstration of four really simple "one-liners" in PHP together to accompany this item. They are:
1. Including the date on your page (look - it's up to date)
2. Using an image that changes automatically every so often
3. Bringing in a "Message of the day" from a text file
4. Having a page include its own URL (very useful if people print the page!)

You can run the demonstration here and you'll find that I've added a fifth one-liner that lets you see the source code too - that means that you can use any of my techniques on your page. Please feel free to do so - although I would appreciate a link back to http://www.wellho.net

You may not even need to change the file extension to use PHP - if you look after your own web server, or if you're got an ISP who allows it, you may be able to add the following:
AddType application/x-httpd-php .html
to a file called .htaccess in your document directory and all pages will then have the HTML++ capabilities!

Posted by gje at 08:06 AM


Useful link: PHP training

February 25, 2006

Behind every face is a person and a story

"That's a lovely piece of cloth". What an unexpected comment from the office and facilities gent who was helping me move my laptops from the loading bay to the boardroom. There's so much we view, but don't see, isn't there? Raymond, who's always on hand when I run courses at this Central Glasgow location, used to be a supervisor in the linen industry up the Clyde valley from here. He still looks at cloth and materials with a professional's eye; with the industry in which he used to work no longer in the area, he now undertakes a daily long commute from his cottage set high in the southern upland hills and a long way from the City.

"Lest I forget" ... behind every person I come into contact with is a personality, likes, dislikes and a full and often interesting life. I'm often baffled when I see people being rude and arrogant with others and giving them a hard time; they're closing the door on someone who could be a good friend and contact, and I'll bet THEY wouldn't like to be treated in that way.

Posted by gje at 01:24 PM

February 24, 2006

Queues and barrel rolls in Perl

There are some applications where you want to go round and round a list and one way to do so is to "barrel roll" the list by moving the last element onto the start each time you use an element. That would be complicated in some languages, but in Perl you can simply use a pop followed by an unshift. Thus:

@hehad = ("Chicken","Feta","Rice","Sticky toffee pudding");
unshift @hehad,(pop @hehad);

And if you want a queue - simply push onto a list and unshift off ... once you get a false value back, your queue is empty.

Posted by gje at 12:11 AM


Useful link: Perl training

February 23, 2006

And the staff put the icing on the cake

I do enjoy taking a ferry in the middle of a long drive. It's a chance to pause, to think, to relax, to eat; I find the "relax" part sadly lacking when I fly.

I'm seated in the Cafe on the "European Highlander", outbound from Larne to Cairnryan, and due there just before 10 p.m. There's quite a bit of freight on board, but only a handful of cars this Wednesday evening, and I'm enjoying the "meal deal" which is rather better, and rather better value, that I'm use to finding on some of the other ferry lines.

Although it's self service, Miguel, the gentleman on the till wanders over and asks me if I'm ready for my dessert ... comes back a few minutes later with piping hot apple pie and custard and bearing a spoon too. "Great minds think alike" I tell him as he sees the spoon I picked up earlier. Let's be fair - I'm not claiming much for my mind, but I will for his. Here you see someone who's working the route day in, day out, and still looking out for his customers - even one that he's never seen before - beyond the call of duty.

Posted by gje at 06:14 AM

Familiar names, close to home

Familiar names - Crossmaglan and Hillsborough, Divvis and Falls - all signposted off the road as I drove from Dublin to Belfast to Larne last night - a course ended at Dublin at 4pm with an airport running dropping off a customer for his flight to Copenhagen, then on through Ireland and Northern Ireland to catch the 20:00 boat to Scotland. So many countries, so little time, and not a chance to stop and explore.

Even in the dark, though, you can see there are things worth exploring; a flatlands in Ireland gives rise to an abrupt line of hills as you drive into Ulster, then down into a great bowl that houses Belfast. Onward, out of the bowl and along higher ground to another drop into Larne, and "The European Highlander" caught with a few minutes to spare. How on earth have I waited for fifty years to even pass through this place so close to home?

Posted by gje at 06:13 AM

If its Sunday, it must be the Norland

One of those weeks where I seem to be sleeping in a different bed(room) every day ... and what a contrast.


From the height of luxury in London to a nice berth on a ferry ...


.... then on to a hotel room, mid-market, Dublin.


Tonight, Kilmarnock! Very late arrival ...



Posted by gje at 01:55 AM

Perl - its up to YOU to check your file opened

When you open a file in Perl, you should ALWAYS check the return status to see if your open function worked. If it can't open the file you've requested it won't print out an error - the failure is silent unless you check for it.

Thus:

open (FH,"abc.txt") or die ("Cannot open abc.txt\n");
Perl will fail to open a file for read if the file does not exist, or if the file is not readable by the user requesting it

open (FH,">abc.txt") or die ("Cannot open abc.txt\n");
Perl will fail to open a file for write if the user running the Perl program does not have appropiate write permissions. A file can be opened for write whether or not it already exists; if it does exist the open statement shown will cause the existing content to be deleted.

Posted by gje at 12:53 AM


Useful link: Perl training

February 22, 2006

Easy, Free, Reliable internet access

[Written last Sunday morning ... and JUST posted on Wednesday!]

Internet access from Well House Manor will be free, easy, and reliable. But accidents do happen and service can be lost. We will go one step further and monitor the service to ensure that we become aware of any problems and can fix them quickly or provide an alternative. Perhaps I sound like I'm preaching here? Yes, to some extent I am as I'm somewhat frustrated as I try to get online this morning ...

Most hotels that are providing an Internet facility charge extra for it through a login / credit card-type system. I understand why. A small proportion of typical guests will use the facility and it costs money to install and run; therefore, most people wouldn't appreciate a price rise built-in to the hotel charge when the facility they weren't going to use was added.

But at what price comes the charging system? I stay in a lot of hotels that run such a scheme and there's a number of pages to go through to get online, a need to choose how long you want BEFORE you know how much time you need to answer your emails and sometimes - as this morning - a system you sign up to for a period of 24 hours just to find that it's intermittent at best. No - for our market we can provide a much more appropriate solution.

Posted by gje at 06:50 AM

printf - a flawed but useful function

Many languages have printf statements ... and yet from a computer scientist's viewpoint, printf is a flawed function. In order for code to be clean and re-usable, functions should be designed to perform a single task. Alas, printf performs two tasks - it both formats the information that's entered in to it AND it then sends that information to an output stream.

What's the better alternative? Where you have printf, you probably have sprintf as well and that's a much better function - it just returns you the formatted string. So I'm advocating that, in Perl for example, you should write:

$tstring = sprintf("%02d:%02d",$hour,$min);
print ("Ths time of this record was $tstring\n");

Posted by gje at 06:34 AM

February 21, 2006

Looking for leading not bleeding edge

When I use a swimming pool, I'm always very conscious of the safety equipment and lifeguards, and also of the other pool users and what they're doing. I have an especial eye for the quiet ones and any places out of common / easy view. Am I odd in this approach when I'm just out for a bit of exercise and a quick swim? No - I was trained as a lifeguard many years ago and the training has stuck.

Attitude to what's around varies person by person - some is nature and some nurture, and the nurture varies over time. I write this seated in a hotel room, where a year ago I would only have been semi-aware of many of the facilities - choosing to ignore hairdryers, trouser presses and hotel stationery and only noting the phone as a useful plug-in for my laptop, perhaps, and the spare pile of towels and something that - well - some people use a lot of towels, so I suppose they're right to provide them.

With the Well House Manor project so well under way, I'm now being more observant; a look at each and every aspect of the room and a thought of "do we / should we" - either emulate, note as interesting but not for us, or actively avoid.

One of the things that especially interested us about the Bentley Kempinski hotel in London was / is its use of a modern, electronic phone / lighting / heating / access control unit in each room. It seems very attractive from a guest viewpoint to be able to control everything from the one unit, and from a hotel operator's viewpoint to know when a light bulb is out without having to do a daily check when a room is let.

Alas, the system doesn't *quite* match up to our user expectations. The screen is dim and requires us to select an icon to brighten it up - difficult on the bright afternoon we arrived. The unit does provide a clock, but you can't see that in the night without switching the thing on. Icons leave you guessing as to exactly what they mean and whilst you CAN get to the thermostat menu, you're quite likely to go past the current time in Tokyo and the outside temperature and the hotel's listing of their restaurants on the way. And the stunning give-away? Beside the unit, which includes a telephone, is another telephone ...

We're looking to use leading edge technology. But we must not make in bleeding edge where something is so new and way-out that we come acropper with it. Even without my carrying on to review the installation and other issues, the Inncom system as used here is ruled out simply on guest experience grounds.

Posted by gje at 07:33 AM

February 20, 2006

News in Ireland

Dublin, Ireland, 07:30. The security guard greets me like a long lost friend and asks after the Taxi that I used to drive with a big Well House Consultants logo on the side.

I've arrived early for a course - the ferry from Liverpool docked half an hour early at 05:30 and there's - how do I put it - not a lot to do in Dublin port or City at that hour, and it's just half an hour or so from the Docks to the place I'm training at. So I sit here in the company's reception and waiting my contact - Perl course for 9 coming up.

On the radio, the news in Ireland is all about a road accident in Buncrana, County Donegal, in which 4 Latvians and a Lithuanian were killed. Many folks from Eastern Europe have moved to Ireland in recent times and are doing some of the rougher, lower paid jobs that the local don't want, even out in the remote parts. They're sending money home each month, and the radio was doing a biography of them - how they had come to Ireland to work, and talking about their children back home in the Baltic states. Tough lives snuffed out early.

The radio then started on about the Cistine Chapel in the Vatican, and how the Pope wouldn't allow just anyone to do the maintenance work on ... just like BMW wouldn't let just anyone work on their cars - only the "chosen ones". Truly, a taste of advertising that could only be Irish.

Posted by gje at 05:55 PM

Greetings from Dublin

My boat docked early this morning - 05:30 - at Dublin Port and I'm back on line after an absence of 48 hours which is unheard-of for me. Further posting (including some note already waiting on my laptop!) later today.

Perl course starts in about 10 minutes ... I'm all set up and ready to go!

Posted by gje at 08:52 AM

February 18, 2006

Coming or going?

Well - that's been one heck of a week and I don't know if I'm coming or going!

Excellent course in Gloucester - a great group of delegates and a real opportunity to show another 9 people what a fabulous language Perl is, and how it can be really useful in what they're doing. To give them some practical experience, and to show them how to write code that is not only good at doing its job but will also be maintainable into the future. Yes - I know that I give courses week in and week out but the joy of the subjects I choose to teach never ceases to enthuse me!.

So what else on that full week?

Well - we've had the unwelcome news that the next draft timetable for the train service to Melksham slashes the services to just 2 a day each way - and one in each direction seems to be timed to suit the operational convenience of the operator rather than any traffic surveys we've done. See my efforts on the Save the Train web site and press coverage

On a much more positive note, we've exchanged contracts on Well House Manor so, barring an unsuccessful planning application, we'll be offering business accommodation included with our training courses, and taking in visitors to other businesses in the town when we don't have a course running here. Although this is an enormous positive, there's been the usual round of papers flying back and forth between solicitors, accountants, vendor, purchaser with things crossing in the post, little issues getting blown into big ones and vice versa.

And as you may have read yesterday, I got a phone call telling me that son Chris was (and still is) in hospital after a road accident. The good news is that it's "just" a broken leg and give him a couple of months he will be as right as rain ... but that was hardly what we wanted to happen. As you can imagine, lots of family activity on this - Chris himself seems to be the quiet eye at the lull of the storm although he's frustratingly bored lying unable to move in a cast in Frenchay Hospital.

Are we in for a quieter week upcoming?

No - "pigs might fly"!

Off to a trade show in London tomorrow to see all the latest in hotel and accommodation offerings; we're working our way very seriously into this and there's a big learning curve. Then I'm off directly to Liverpool for the Dublin ferry - a course there on Monday through Wednesday.

Then what?

Amazingly, I don't know. We DO have a course booked in Glasgow on Thursday and Friday next, but a phone call and email late on Friday afternoon asked about postponement so that the customer can get more people together, and we didn't hear about it until our contact was gone for the weekend. Lisa's going to have to deal with that at the start of next week. And I'm going to have to go to Dublin with all the resources I need whether I'm coming back to the office or carrying on to Glasgow later in the week.

One thing's for sure, it's not going to be a boring week!

Posted by gje at 09:30 AM

February 17, 2006

Look out for the motor cyclist

I visited my son Chris in hospital last night.

He's awaiting an operation, scheduled for today, to put the pieces of one of the bones in his lower leg back together - the registrar came around while I was there and described the operation as being rather like putting a kebab skewer in to gather the pieces and hold them. It requires a general anesthetic and he was being taken through what will happen in the operation and the risks.

Chris was on his (motor) cycle yesterday when some [description deleted] pulled out in front of him; he swerved to avoid going over the bonnet, but couldn't miss completely. Looks like the car driver is in considerable hot water for dangerous driving. Thank goodness Chris had invested considerably in good (now ruined!) protective clothing as it saved him from much worse injuries. And thank goodness that he's something of a safety aware driver ...

Premonition? I don't think so, but I was very minded yesterday morning as I drove up to Gloucester to run a Perl course that there are certain road junctions where you need to REALLY watch out for the motor cyclist; I'm very much aware of the current TV adverts on the topic and on places like the A433 / A429 corner south of Cirencester they can appear from no-where.

P.S. Chris is very well / controlled in himself, and commissioned me to write this blog entry as a rant against motorists who don't watch out for motor cyclists!

Posted by gje at 06:03 AM

February 16, 2006

Need a hankie

I was walking round a branch of Sainsbury's I didn't know yesterday and looking for paper hankies. Where did I eventually find them? Under "Seasonal Goods". Hmm - obvious once you know.

Posted by gje at 04:48 AM

Been on a course, but still not got it?

Attending a course is one thing, but usefully applying what you learnt can be another if the course just taught you the mechanism. And whoever's course you attend, you need to practise afterwards, and have some way you can get back and ask questions. There's a follow-up responsibility on both the course taker and the course provider.

I'm going to share with you part of a response I wrote to someone who has attended a mechanistic PHP course ....

"I understand that you've already attended a course that included some PHP, though not one of ours; if you're needing further help on what you learnt, can suggest that you might also be provided with an element of ongoing help from the trainer or organiser of that course - that's certainly a service we provide here at Well House Consultants for our delegates, and chances are that your tutor knows you and your application a bit already.

Programming is an art as well as a science, and you do need to practise and get into the flow of things as well as having taken the course. I take great care when I teach to ensure that I cover not only the mechanism of specific examples but also the techniques for adapting and applying those techniques. There's something of a parallel to a creative writing course, where copying the tutor's work really won't do much for you."

Yes, I do find it slightly ironic that I'm being asked to provide help by someone who's just bought (a course) from a competitor but, what the heck, this business is all about networking and I know how hard it is to choose the right course - after all, if you knew what you were looking for, you wouldn't need a course, would you?

Posted by gje at 04:40 AM

February 15, 2006

Don't expose your regular expressions

If you're writing an application, it's generally NOT a good idea to take a user input and slap it straight in to a regular expression for matching - quite simply because it's improbable that your user will be familiar with regular expressions and he / she will get all sorts of strange results if she / he puts any special characters into their search string.

Users do often require to enter various search patterns, and I recommend that you come up with a scheme that suits your own type of search; that might involve taking the user's input and using it to indirectly for a regular expression, or it might make for some totally different search.

I was talking about this yesterday to a Perl group, with a user community that's used to using * and ? in file name matching (know as globbing) and who want to do the same on data within Perl. It's a good example where the program shouldn't just pass through the data entered - rather, they should
1. Protect input special characters with a \
2. replace input ? characters with a .
3. replace input * characters with a .*
4. Add ^ and $ anchors

And that will give them the ability to wildcard in the good ole way they wish!

Posted by gje at 07:00 AM

February 14, 2006

On being British

My Grandmother never passed a driving test, yet she drove a car. My Mum drove a car and although she passed her test on an automatic, she was qualified to drive with gears too. I didn't have to take a theory test, but still I'm fully qualified to drive. My daughter had to pass theory and practical (done with flying colours) and has now been through more hurdles than any of the previous three generations.

I heard on the radio yesterday that there's a backlog of some 70000 applications for British Citizenship in a queue; more complex and stringent requirements were introduced not too long ago and the new system appears not to have been ready and waiting when the doors were opened. Included in the new requirements are the ability to communicate in one of the official languages (English or Welsh) and to know about the country and its systems. Not a bad thing. And it also includes a ceremony to welcome the new Britons; I wondered about that when I first heard of it, but Lisa (who became a British citizen before the new system was in place) is all in favour - she expressed a great disappointment that what was the final step of belonging in the UK arrived as a somewhat plain certificate in the post one morning.

So what IS "being British"? I think it's feeling you belong in the UK and that it's your permanent home; you foresee staying here the rest of your life even if something were to happen to your SO. That doesn't mean that you have to understand every question in the citizenship test - heck - *I* couldn't tell you which courts sit with and without a jury - but it does mean that you'll want to gain a great deal of that knowledge.

This summer, my daughter in law will swell the queue by a further one as she completes her length-of-residency requirement. As far as I'm concerned, though, she's already British.

Posted by gje at 07:53 PM

Train service from December

Really one for our other (save the train) web site ... but the draft timetable for Melksham from December 2006 has been published.

As widely predicted, cut to two trains a day. Sadly, little notice has been taken of the requests for a slightly later arrival in Swindon in the morning of the commuter train (no - it now arrives a quarter of an hour earlier), nor for a slightly earlier departure in the evening (It's over half an hour later). I expect that these changes will drive away much of the existing commuter traffic - I hope that it will find a new traffic to replace the loss.

From a Well House Consultants viewpoint, the 09:12 arrival from London no longer runs - there are early morning trains into Melksham at 06:46 and 07:37 - too early for our customers, and neither has a connection from London because they're that early.

The 17:02 departure is gone too. At the end of a course, the best we'll be able to offer trainees from Melksham is an 18:38 departure that will get them to London at 20:51.

Not necessarily all doom and gloom. I expect we'll be encouraging delegates to travel down on the 17:00 or 17:33 trains from London the night before their course starts, and connect into trains that arrive in Melksham at 18:38 or 19:28. We'll be delighted to pick them up from Melksham Station and take them to Well House Manor where they can get a good nights sleep before starting their course fresh the next morning.

At the end of their course, we'll make arrangements for trainees to get to Westbury or Chippenham stations for a return train, or they'll be welcome to stay a further night and we'll take them for the early train to get them to London for a quarter past 9.

Posted by gje at 01:53 AM

February 13, 2006

Design your day with a walk

Walking to work does wonders for your efficiency. So I was told by a chap I trained last week, and he's right. One of the things I miss by working from home is a stretch of time in which to think about what I'm going to do, or what I have done. Design MATTERS ... as we say on the Perl course ... and the walking time is the time to design your day.

I'm commuting by car from Melksham to Gloucester this week - a five day course, and it's giving me elements of time to think quietly. Nothing like as good as walking or taking the train, but something; you'll see me fired up and writing what - I hope - are quite interesting entries here and I'll certainly finish the week with plans in my head.

Posted by gje at 06:52 PM

Perl - multiprocess applications

There are times that you'll be writing an application that you want to go off and perform task "x" and AT THE SAME TIME have it perform task "y", co-ordinating task "y" with task "x". Threading (NOT the subject covered here) is one possible approach. And another possible approach is forking. How does that work?

Let's say that you want to write a process that receives requests from a number of different clients and handles them sequentially - but quite slowly. A print driver would be a good example ...

1. Set up the main (to be monitoring) process, open a port, wait for requests.

2. When a request is received, note you process ID (the $$ variable), set up a pipe then fork.

The effect of the fork is to split your single process into a parent and a child each of which has copies of all your variables and each of which can continue on its own way.

You recognise that you're in the child process because the fork function returns a false value, whereas in the parent it returns the child's process ID.

The parent can then resume its wait loop, and the child can process the data.

3. When the child wants to talk to the parent, or vice versa, it can write to the pipe. A pipe opened before a fork connects any writes on the parent to reads on the child, and any writes on the child to reads on the parent.

4. If the child or parent needs to communicate with the other asyncronously (i.e. when the other is NOT waiting for an input), you use a signal. Signals are sent by the alarmingly named kill function, and collected by a sub that you've named in the %SIG hash in the receiver.

If you're writing a Perl program that forks, have a look too at the $| or autoflush special variable, and both of the select functions that are built in - one to set the default channel, and the other to check whether there's any data in your read buffers without having to wait if there isn't. Note also the use of temporary files to transfer information, and perhaps look at shared memory.

There's a simple fork example and also a more complex talker written in Perl available on our site. Training (with practicals) is available if you're attending Perl on the Web or Perl for larger projects.

Posted by gje at 06:07 AM


Useful link: Perl training

PHP - setting sort order with an associative array

I was updating one of our web site scripts a few hours back, and I wanted to sort the rows of an HTML table generated by the PHP from a directory listing. Problem was that I was making the table up using concatanation (.=) operators in a single string.

First solution - put all the table rows into an array and sort the array. Alas, this solution was ugly because the usort routine needed to sort the list some ugly code to unpick the table rows that I had just carefully created.

Second solution - and very neat though I say it myself - was to put the table rows into an associative array and set up the keys of the array to be the sort key. All I need to then is a ksort to get the rows in order, and an implode to join up the values in the table since implode ignores the keys if its input is associative

Code:

$fill = array();
$dh = opendir($source);
while ($name = readdir($dh)) {
 /* code to work out the table row ... */
 $fill[$name] = /* Nasty per-line code! */
}
ksort($fill);
$fillit = implode("",$fill);

Posted by gje at 12:39 AM


Useful link: PHP training

February 12, 2006

MP face to face

On Friday, I met Dr Andrew Murrison MP in his constituency office in Trowbridge, to fill him in on potential flaws in some "footfall" statistics on threatened train services such as the "TransWilts" and the Bristol to Waterloo which provides the only direct trains to London from 3 of the towns in his constituency.

I'm a bit of a political cynic, but I have to admit to being impressed. Dr Murrison is more a medical than a transport man. He was well informed, yet knew the limits of his knowledge. A sharp mind, able to come back with good and pertinent questions (including difficult ones) too.

It's also good to see how quiet and without fanfare the whole MP's operation is - at least in this particular case. A discreet office, a pleasant reception staff, an offer of a coffee, and the chance to put some very niche / specialist points in an unhurried way. Perhaps that's just the way it is in the South West of England and things would be much more frenetic in London.

Posted by gje at 05:41 AM

February 11, 2006

A fond memory of Sir Freddie

A tribute - and a thank you - to Freddie Laker who passed away on Thursday at the age of 83.

After the headline-grabbing, innovative-ahead-of-its-time, operation of Sky Train that failed because it was also vested-interest-annoying, Sir Freddie set up another much less know operation based in Freeport in the Bahamas, simply known as "Laker". From 1996 to 1998, he ran a daily flight with a Tristar airbus from Fort Lauderdale in Florida to London's Gatwick.

When Lisa lives in Florida and I was in the UK, we often used Sir Freddie's service back and forth. It was cheap, it was cheerful and (alas, poor Sir Freddie) it was rarely booked up too far ahead. The plane was quite an old one, and would get held back in Florida to ensure that fog at Gatwick had lifed before it arrived there as it needed good visuals.

I recall one day being boarded, and then being unboarded as we had to wait an hour or two. And I recall that Sir Freddie, who happened to be on hand in his Laker offices based nearby, came down personally to apologise to the passenger, to shake their hands, and to wish them a good, if somewhat delayed flight. A great pioneer who I remember fondly, and who will be sadly missed.

Posted by gje at 08:55 AM

It costs nothing to say THANK YOU

If someone spends a time writing you a letter, and does so above and beyond the call of duty or their job, then it's an act of kindness and a brief "thank you" is called for - at least in my book. In times gone by, that meant scribbling a note on a piece of paper, putting a stamp on it and popping it in the post, or picking up the phone and making a quick call. But these days, with nearly all my correspondence being on line, it's even easier and even cheaper. It costs nothing but a couple of minutes of someone's time to say "Thank you".

Sadly, there's a number of people out there who don't, I've surmised, even think of acknowledging help and advise given. I'm afraid that I can even see something of a trend in my incoming mail box and make an educated guess as to which ones are unlikely even come back with the minimal of courtesys - and they're NOT necessarily the ones you would expect either! However, there are lots of exceptions to every trend and I will continue to go on answering even the errant groups; I'm more easily surprised by any politeness shown, and I often learn things as I research my answer.

As I wrote this piece, I did a search back through the blog looking for "rude old people". I was thinking of an incident in Torquay where a sprightly pensioner couple forced my stepson off the pavement and into the track of oncoming cars, acting as if they owned the road. And what I came up with was the cow (sorry - that's unfair to cattle) who queue jumped on the Geek Cruise. The reason I'm seething today is that I took time out to research and answer a woman who wrote with a proud "I am 70 and" in her email asking for help ...

Posted by gje at 07:18 AM

February 10, 2006

Perl/Tk real time display

It's a real pleasure to be having an opportunity at the tail end of this week to write some examples that are combining Perl, Tk, and OO techniques. This clock is generated on a canvas, and updates every second. It's generated in its own frame and schedules its own events, so you could easily use it within part of your own GUI if you wished. The hour, minute and second markers are all instances of an object of class hand, also defined within the example, and all the calls to the trig functions that are needed to work out the hand mappings and movements are encapsulated in there.

Tk's powerful canvas handling tools allow the text to be centred without complex calculations, and the display list technology it uses allows the hand markers to be moved without the need for repaint routines - it's truely impressive what can be done within a very few Kbytes of source

Posted by gje at 12:38 AM


Useful link: Perl training

February 09, 2006

Should we cruise around the world?


Cruise Liner in Venice

Waiting for a pizza in the Acropolis on Tuesday, I was reading the material they provided ("The Sun"). A self-evaluation quiz - "how strong is your marriage" - caught my eye for a few seconds and I read (paraphrasing):

Which of these best describes your view of the future?

1. I look forward to the day that we're not together
2. We're saving up for a cruise around the world when we retire.
3. Goodness only know what next year will bring.

OK - it just HAD to be number 3.

A year ago, I wouldn't have expected us to be expanding / growing the way we are with the seismic shift that projects such as Well House Manor will bring ... and as plans for that develop, we're seeing other natural ways of how it will work into our lives. The train campaign - increasing the awareness of the train services to Melksham and the threat they're under - has brought us from being unknown in the town and sitting at home most evenings through to a frenetic series of meetings - "if it's Wednesday it must be ...", and appointments on non-training days that are timed at two-hourly intervals. Not everything has worked out as well as we might have hoped or reasonably expected but - hey - there's a risk in everything and where something doesn't go as planned it can be amended to suit all or, if need be, a decision taken to stop it going too far off the rails.

So, rather than looking back, I look forward and I have to say that the Sun's third option just has to be the right answer. I can add that I'm certain of one thing - that future will be Lisa and Graham in amongst all the aspect marked "don't know" and "we'll see". And one other thing I'm certain of too - we're not looking to tie up just yet!


There was a lovely smell of veggie pizza wafting out from behind the counter, and a young couple came in and wanted to sit where I had the paper open. I didn't continue reading the quiz - I just took a quick look at the scoring for the question that had set me thinking. Option 3 was middle-ranked, but it strikes me that we would be pretty sad and insular if, with all the exciting things we're fortunate to have around us, we were already looking forward to putting the brakes on it all and going off on a boat.

Posted by gje at 07:24 AM

Storing a regular expression in a perl variable

When you match to a regular expression in a perl program, the program has to compile the regular expression (i.e. work out what it does) before actually doing the matching. It's pretty smart about that - it stored the result of than compile so that it only has to do it once during each run. However, if the regular expression contains a variable, Perl is slowed right down as the variable could change and Perl has to recompile every time.

If the variable isn't, in fact, going to change very often during a run you can control the compiling yourself by using a scalar variable to store the compiled regular expression using qr, as shown in this example:

  
$local = "TR|PL|EX|TQ|TA|SN|BA|BS|DT|BH|GL";
$pcode = qr/^\s*($local)\d\w?\s+\d[A-Z]{2}\s*$/;

@vcheck = ("SN12 6QL","G3 7XR","GLZ 7PX"," OX11 0EY","NW1 1AD");

foreach $tp (@vcheck) {
$tp =~ $pcode and print "$1\n";
}

This gave me the single result "SN" as being the only valid postcode within the areas listed in $local.

Posted by gje at 05:08 AM


Useful link: Perl training

February 08, 2006

The magic of -textvariable

If you're writing a GUI based application, you'll need to hold pertinent information in variables in your program, AND display that pertinent information to the user.

The obvious way of doing this is to provide code that updates the display as required - in the case of Tcl/Tk you might write
   .wname configure -text "Melksham"
to change the text on the button called "wname" to Melksham, and
   set usersays [.wenter cget -text]
to read the text that the user's put into an entry box.

But there's a better alternative. Many widgets support the -textvariable option which allows the widget to be a reflection of the variable in your program all the time - in other words, if your program changes a variable then it will be automatically updated within the widget display, and if the user changes text within an entry box that's set up with this feature, then the variable within your program is automatically updated. Examples:
   entry .username -textvariable uname
   label .host -textvariable hostsystemname

Complete source code examples -
A Tcl/Tk form
In a Tcl/Tk popup message box
A Perl/Tk example

Posted by gje at 08:39 AM

Add a friendly front end with Tk

With a Tk Graphic User Interface, you can add a friendly look and feel to an application running on your workstation if it's written in Tcl (Tcl/Tk), Perl (Perl/Tk) or Python (TkInter).

Whichever language you build your GUI on to, you'll want to remember

1. Create your components (known as widgets) as your application starts - you'll have buttons and labels and entry boxes and frames ... and associated with some of them such as the buttons you'll have commands that are to be run later on when the button is pressed

2. Use a geometry manager to position the widgets within the application window(s) and to define how they're to react when the window is resized

3. Define any extra events - things that are to happen when the user interacts with the GUI - in addition to the commands that you specified as you defined the components.

Once you've created the components, added extra events, and placed the components you can sit back and let the application run in what's known as the event loop. That's a loop - and it can be an infinite loop - that waits for the next event, and when it's received, you process it.

The source code of the example used to illustrate this item is only a few hundred bytes long and much of that is comments. You can view the source code if you wish.

Posted by gje at 05:48 AM

February 07, 2006

Twice is a co-incidence and three times is a pattern

Open Source training from Well House Consultants started from just three customer requests for a Perl course.

I was using Perl for various web site and internal works, and training under contract - so I suppose I was a natural one to ask. By I hadn't given a clue to people that I could / would write my own material.

I'm afraid I told the first person that I hadn't seen much call for the course. "Who's going to pay for training on a piece of free software?" I think I asked.

The second person got a rather more muted "No - sorry". After all, it's said to take some ten days of course material development for a single brand new day of presentation.

I stopped myself just before saying "I keep telling people - there's no call for that ..." to the third person and the rest, they say, is history.

Public Perl courses started in 1996. From an occasional Open Source public course that year within the environment in which I was contracting, I move to presenting only my own material a couple of years later, and the Well House Consultants training centre opened its doors in 2000. Later this year, we're adding our own residential accommodation for delegates who travel far and wide for our courses, and we'll have an additional and larger room available for training too. Onwards and upwards!

And look ... all of this started from just three customer requests ...

Posted by gje at 05:06 AM

February 06, 2006

Finding where the disc space has gone

Murphy's fourth law states that data expands to fill the disc space available, and there's a collaboration that states that it reaches that full point when you're trying to save a file you should have saved a long time ago during a complex operation.

I'm not a good one at deleting old backup files; I tend to have directories marked "january 06" and things like that; in that way I can go back to "when" and find old stuff. I want to know about the Geek cruise? Why - those notes are in October '04. Not sure of a date? A background grep can find stuff for me. So I've been running at 90% full for a while. Applications have been starting to grumble a little, and were starting to get a little bit more upset over the last day or two. Not helped by a mailbox that's getting hit by a fair flow of spams / viruses of about 179k each that get put in the trash quickly enough, but then stay there until the dustman commeth.

I'm on an OS X box. These same commands work for Linux and Solaris too:

df -k How full are my discs?

du -sk How big is the current directory and everything below it?

du -k How big is the current directory tree, directory by directory

du -sk * How big is EACH entity in the current directory? Really Useful!

It was using a du -sk * on my home directory that brought me, a few minutes ago, to an aptly named directory called "huge" of some 18Gbytes. A 2Gb copy of the entire DMOZ database, plus a 6 Gyte file that contained the entire thing replicated 3 times over, and a further copy of that 6Gbyte file chunked up into units of just 1Gbyte. The result of some well remembered, logged, important work on how Python can handle huge files, but some temporary data that was able to release 15% of my disc space with a single rm.

Posted by gje at 06:37 PM

February 05, 2006

NOT Gone phishing

Early last week, I was giving a training course on Perl and talking a little bit about Perl objects - how all the internal logic that's associated with a particular type of data can be hidden within a source file so that the person writing the code to call it up only needs to understand what to put in, and what's returned. This characteristic is known as encapsulation and it allows a medium to large sides application to be built and tested stage by stage leading to more robust code that can be easily maintained.

It's my norm during such training sessions to select a delegate at random, ask him what his hobby is, and write a class of objects based on that. During the demonstration, it shows that only the expert (hobbyist) need know the technical detail - all the users can simply build on his encapsulated skills. But last week, I rather took my delegate by surprise and he didn't suggest anything. "Fishing" I said and he looked glum; alas - he felt as I do that fishing is cruel as wasn't happy. So as a compromise, we switched to phishing.

Phishing (with a P-H) is the new term for sending out emails purporting to be from a major financial institution and asking users to log in, via a link in the email to the web site to update their contact details. Except that the web site link is NOT back to the real site of the institution, but rather back to a fraudster who gathers the personal information entered ... giving him access to his victim's identity and bank account. Truely a nasty business.

On Thursday evening, I went along to a meeting of a local business committee that I had been invited to join (a story for another blog, perhaps) and one of the subjects that came up there was Phishing by phone. It seems that there's a line of fraudsters out there at the moment who are phoning people and pretending to be from their bank. "For security purposes" they're asking for details such as the 3 digit code printed on the rear of your card .... Oops.

I always try to be very careful when I'm phoned up by someone who says they're from the Bank. Alas, often they really are from the bank, but I've taken to asking them security questions in reverse ... for example, I might ask them about a recent transaction on my account rather than the other way around. Only rarely will they co-operate; even though THEY are the ones who phoned me and they must know they called the right number, they're not allowed to trust that they dialled correctly. Odd, isn't it, how there's one set of rules for them ...

How to break this mutual lack of trust, thrust on us by the phishermen? Well - if you ask your caller for their email address and insist that they give you one on the bank's main domain, I think that's a good step. You can then email them and ask them to call you back quoting something from the email. It's not going to save you against an "inside job", but it will mean that you've put them over a hurdle that should be easy enough for the genuine caller, but tough for the fraudster.

What a long way from my phisherman class, which can be found at this link and you can learn all about on this course

Posted by gje at 10:24 AM

February 04, 2006

Key facts - SQL and MySQL

Some quick ways to remember your SQL; here are some "flashbulb moments" for newcomers and occasional users of MySQL and other SQL databases.

A database daemon is a process that looks after a number of DATABASES each of which comprises a number of TABLES each of which comprises data arranges in ROWS and COLUMNS.

You don't access database information directly on the disc from any application program - you access it via your database daemon (a program called mysqld) which is usually running all the time and MUST be running whenever you want to access your data.

You SHOW to look at the structure but you SELECT to look at the content.

You UPDATE the content of table rows but you You ALTER the structure of a table.

You choose rows from a result set with a WHERE clause but you choose rows after you've grouped them with a HAVING clause.

You add tables to each other "side by side" with a JOIN and you add results sets above/below each other with a UNION.

You use a USE command (or other function call) to set the current DATABASE but there is no concept of current TABLE to carry through from one query to the next on a connection.

REPLACE gets rid of existing rows and puts new data in their place, but UPDATE changes existing rows in situe and leaves columns that you don't re-specify unaltered. DELETE gets rid of rows completely, and INSERT puts in completely new rows.

Every row in a table has the same structure (homogeneous) but different columns will have different structures (hetrogeneous).

If you JOIN tables, you tell MySQL how the tables are to be connected to each other (which row(s) in the first table match which row(s) in the second) using an ON clause.

A regular JOIN return only result rows where the ON clause matches up a row from each table exactly, and a LEFT JOIN return the same results and IN ADDITION any records from the left hand table specified, NULL padded to make a complete result record.

You use = to check whether something has an exact value, but you use IS NULL to check for the total absence of any defined value.

Some useful resources ...

See our MySQL FAQ for further useful articles and the main MySQL web site for the full MySQL reference manual.

We teach private MySQL courses at our centre and we run public courses too. If you've a group of trainees who all need the same course at the same time, we can run a course at your office too.

We run a user forum where you can ask questions to which you can't easily find the answer elsewhere, and we post up longer articles in our solution centre. Further information is grouped by topic such as SQL Primer, more complex SQL commands, MySQL installation and admin, how to design a database and writing applications to use a database.

Posted by gje at 06:01 AM

February 03, 2006

Danny and Donna are getting married

"Can I write a very quick Perl script to run a wedding list, where items are marked off as bought once someone has put their name against them?". So wrote Danny, hoping to get his online friends to fund large parts of his round the world trip ...

My normal reaction would be to say "look, Danny - if you don't know Perl, that's going to be a lot of work unless you're planning to get married many times and keep re-using the same script". But then I thought - perhaps it COULD be done as a short demo.

Have a look at the page I came up with which includes all the program and HTML elements in a single page - it's the basis for Danny's application. You'll find the source code is available too - please feel free to take this and modify it to deal with other applications ("who will bring what drink to the party").

Remember, though - it's just a basis. My test code needs "crisping up" a bit - and you would want to add in some emailing capabilities too. I expect you would also want to remove the bit that resets the application to offer everything all over again when the list is complete - but then that's a feature that makes it into an excellent little learning demo!

Posted by gje at 07:06 AM

Robust PHP user inputs

If you write a script in PHP, it's one thing handing benign user inputs, and quite another "bullet proofing" your script against awkward characters (of the "less than" and "double quote" type) entered into form fields where they can lead to problems of the SQL error, echo display corruption and injection attack style.

I use the following diagram on PHP courses to remind trainees of the need to clean us EVERY user entry variable and to process EVERY string that's send out to a database or as part of the HTML response:

Remember that PHP was designed to handle web page work, so this string cleansing can be done with built in functions - there's a function to do that as we say during courses!

Just be aware ... that there are other issues as well as the ones shown in our diagram. If you're looking to write cast iron (squaddie proof) PHP, you'll need to use regular expressions to check that the inputs made of are of the format your program expects, you'll have to ensure that register globals is off or that every variable is initialised, and you'll need to check that users don't enter file names starting with "/" or "../".

Posted by gje at 06:16 AM


Useful link: PHP training

February 02, 2006

Changing @INC - where Perl loads its modules

Where does Perl load modules from in its use and require statements? It loads them from directorys in a special list called @INC, from files with a .pm extension in those directorys.

When Perl's installed, @INC is set to a list of directorys that includes generic locations for its standard modules, some release specific directories, and "." the current directory, which are checked in order each time you do a use or require.

Some ways to modify @INC

** You can add to the list in @INC by using the -I command line option:
perl -I /Users/grahamellis/jan06 i2
says "run the perl program i2, additionally checking the jan06 directory for modules"

** You can add to the list within your program by doing so in a BEGIN block prior to the use statements:

BEGIN {
push @INC,"/Users/grahamellis/jan06";
}
use demo;
print "hello world";

Rather curiously, use calls are run at compile time not at run time ... but then so are BEGIN blocks ... so you put your manipulation of @INC into one of those to get it to happen early enough.

** You can add to the beginning of the list by setting the PERL5LIB environment variable prior to running your program:
export PERL5LIB=/Users/grahamellis/jan06
and you can use a colon separated list for that if you want to pre-pend more than one directory.


Footnote - don't you just love Perl's "There's more than one way to do it". Thanks to Dave Cross - author of various Perl books - for reminding me of use lib; - see the comments he's added for a description of this in his own words

Posted by gje at 05:41 AM


Useful link: Perl training

Job vacancy - double agent wanted

Seated in a beautiful Italian restaurant overlooking the Pacific in San Diego, California, the Vice President of Zingo [company name changed] suggested that I might like to become a double agent - a spy for his California based arm of Zingo in the Basingstoke office, where I was in the role of European Technical Support Manager.

Times were difficult in the Basingstoke and San Diego offices of Zingo. Products designed and built in California were vital to our customer base in Europe (and to the survival of the European office), but the California office was overstretched and hadn't got the resources to service all the domestic and international markets. I had arrived in San Diego on the previous Sunday, with an instruction from my boss, the international Vice President (based in Basingstoke) to "sit in Dick's office until he gets the quote out for GGB". I had turned up unannounced at the front door on Monday morning, and wandered around to the designated room ... and started a furious row between the VPs. Everyone was fighting for their jobs!

At that lovely lunch, I declined Mick's offer to be his spy in Basingstoke and save my own head. I knew the writing was on the wall anyway and I also knew that if I turned against Peter in Basingstoke and for Mick in San Diego, it would just be a temporary reprieve. Mick wouldn't be able to trust me, I would have let down Peter - a good friend of mine - and I would have had to live with a decision that I felt would be immoral.

I sat the rest of that week in Dick's office. Well - sort of sat - I rolled up my shirt sleeves and knuckled down, helping him write the specification that was needed so desperately in Basingstoke. Dick's a pleasure to work with - a real gent who had made it very high up the US military on merit. In spite of what could have been a horrid week, the two of us did a great job getting the quote for spec for Europe AND the other things that were piled up for Dick out of the door.

Postscript
Mick, the VP in California was so annoyed that he arranged for all European Technical Support to be done out of California and - oh what a co-incidence - my role disappeared.

Dick took early retirement a few months later.

I've completely lost track of Mick. I think I know where Peter is; Peter Still enjoys the cut and thrust of working for US based techno-startups.

Dick and I became firm friends. When he and his wife came to the UK, I took a couple of weeks off and enjoyed showing them around. And we've stayed on numerous occasions with Dick and Dottie in their home in Coronado, and used their ski lodge for some great holidays. We still meet very occasionally when they take a holiday over here, or if I happen to be in California, we chew over old times, and we put it down as a life-building, enriching experience.

Posted by gje at 05:03 AM

Perl Regular Expressions - finding the position and length of the match

If you want to find the position of a match in an incoming string, simply check the length of $` (That's $PREMATCH if you've chosen to use English;) to check where it starts, and add the length of $& (that's $MATCH) to find where it ends.

Lets say I want to find all the URLs refered to in a web page that's loaded into the variable $html. I could write:

push @section,[length($`),length($&mps;),$1]
        while ($html =~ m!(https?://[^ >"]+)!g);

and that will give me a list of 3-element lists containing start point, length and actual string matched. Here's the code to display that list:

foreach $element(@section) {
        print (join(", ",@$element),"\n");
        }

and here's some of the results from the sources of our resources index

5979, 36, http://www.wellho.net/forum/top.html
6967, 36, http://www.wellho.net/net/mouth.html
7059, 42, http://www.wellho.net/downloads/index.html
8369, 67, http://www.wellho.net/mouth/387_Training-course-plans-for-2006.html
9365, 43, http://www.trainingcenter.co.uk/travel.html
9516, 45, http://reiseauskunft.bahn.de/bin/query.exe/en
9599, 59, http://www.livedepartureboards.co.uk/ldb/summary.aspx?T=MKM
9861, 48, https://lightning.he.net/~wellho/net/secure.html

P.S. I loaded my whole web page into a single variable using the code


open (FH,"/Library/WebServer/live_html/resources/index.html");
undef $/;
$html = <FH>;

which is a nice little demo of changing (or removing) the delimiter character for reading from a file handle, via the $/ variable. Once $/ has been undef-fed, reading into a scalar slurps from the current pointer in the file right through to the end of file.

Posted by gje at 04:30 AM


Useful link: Perl training

February 01, 2006

Looking for Python staff

I'm often asked if I know any good Python programmers. And the next sentence is usually along the lines of "I'm looking to add Python programming resources to my team ...".

I do know some excellent Python programmers. Some are people that I've met over years of being in the business, but most are trainees who have been sent on our courses by their employers and who I've seen grow from new users through, in many cases, to expert practitioners.

Well House Consultants is NOT a recruitment agency. Our main commitment is to our delegates and to the companies who pay to sent them to us, so it would be a conflict of interest for me to proceed to help other people recruit them after the course. But there are exceptions; if a trainee has moved on from the employer who sent him on the course, or if he's a contractor who paid for his own place, then I'm happy to pass job opportunities on.

So you're looking for Python staff, I'm only able to offer you a very limited pool. And I can also help you build your own pool. We offer Python training courses; if you want to take on a new team member and get him trained up, or you have an existing employee looking for a new role, what a great solution. And that existing employee will already know your business too so he wouldn't need to learn that too.

Posted by gje at 06:53 AM


Useful link: Python training