Always Get Better

Resumes Are Better Without Alphabet Soup

June 2nd, 2010

You can spot them a mile away – resumes that look like someone loaded up a Microsoft Word template, punched in their information, then sent it to every job posting they could find.

Does this sound at all like your resume?

They probably start with an Objective statement proclaiming the candidate’s desire to secure a position among a progressive and upward-mobile organization.

Next up is the candidate’s skills, a veritable alphabet soup of every technology they ever came across. Honestly, does anybody really have useful knowledge of everything including ASP, Java, C++, Assembly, COBOL, Lisp, Python, Erlang, Ruby, PHP and Haskell? Yes, we get that you are smart and can work in any environment we throw at you, but what are you awesome at? I can’t tell.

Next is education, usually just the program name and sometimes a GPA. No real details about what the program consisted of – the point, after all, is that the candidate has an education, right?

Finally, the awful listing of every company the candidate has ever worked at going all the way back to the summer job they had in high school. Each is illustrated with so many jargon-filled bullet points that the resume takes up three pages and gives no really useful information about the candidate or their skills.

Sad to say, most resumes fit this pattern. The good news for you is the bar is set low which means it can be incredibly easy to stand out from the crowd.

Lose the Objective
The objective statement is the biggest sin academia has thrust into the world. The company you’re applying for does not care about your objectives and long term plan; their concern is finding a skilled worker who can meet their objects. Sorry to re-use a tired paraphrase, but ask yourself what you can do for the company, not what the company can do for you. Leave your expectations out of the mix until you hit the negotiation stage.

Less is More
Rather than listing every programming language you’ve ever heard of, list the top 2 or 3 you’re best at. If that means you can only list PHP because you live breathe and eat it, do so.

This is a bit intuitive: Showing a dozen skills will not keep the doors open for the best possible job. The reverse is true – rather than leaving recruiters confused as to whether you’re a good fit for their job, let them filter you if need be. Think about it – if you are that amazing PHP programmer, do you really want to be developing COBOL on mainframes all day?

Tell a Story
Try to put yourself in the shoes of the person who will be reading your resume. They will be reading other people’s resumes as well, most of which will look alike except for the author name at the top of each page. It should be a fairly easy job – just pick the candidate whose skill set matches the requirements of the job and hire them.

The reality is much more difficult. Even if a manager has the budget needed to hire someone, they may not be able to find the right person to fill the job. Skill is only part of the story – personality also plays a large factor. It isn’t enough to have someone who knows the job; it has to be someone who will fit in with the team and be a pleasure to work with.

Don’t just talk about your skills – talk about you. What do you bring to your work that no one else on earth can duplicate? You could start with a ‘hobbies’ section on your resume, but I recommend injecting as much of your own voice everywhere you can.

Rather than simply describing your job functions for each position you held, write about what your learned during your time at each company. What contributions were you able to make to the bottom line? Remember, your potential employer is hiring you because they want to make money.

Tethering the Internet, Week One

May 29th, 2010

So I’ve been tethering my phone and using it as a backup Internet connection for just over a week now and so far I have been pretty happy with the results.

Using Xplornet as my primary source and my cell phone tethered into my computer via USB, I’m actually able to get fairly reliable service – the computer switches back and forth between whichever connection happens to have access to the Internet.

This could work…

I see that Bell is now offering a 2Mbps modem for rural residents. I’d like to try that as an alternative to Xplornet – maybe I’ll be able to drop my contract in March and have reliable net.

Using a Cell Phone as Backup Internet

May 24th, 2010

Since we live in the country and rely on line-of-sight Internet for our connectivity, I’ve been increasingly frustrated with service quality and uptime programs. There are a lot of reasons I want to move to a denser population area but access to a proper Internet connection is high on my list.

My phone has turned out to be a decent alternative; using instructions I found online I was able to re-purpose my Palm Pre as a WiFi router. It’s still not broadband but it gives me a way to check my email when my Xplornet fixed wireless (often) fails.

Although Bell Canada supports tethering with their smartphone plans, they don’t go out of their way to make it obvious how to do it. My Tether turned out to be worth the cost; even though there is a free version you can use if you want to play with the settings.

Display Class Objects in CheckedListBox

March 28th, 2010

If you want to use anything more complex than a list of strings in a ListBox, you’re in luck because the control accepts all types of objects.

Custom Objects (Blog Posts) Displayed in a CheckListBox

Custom Objects (Blog Posts) Displayed in a CheckListBox

In this case, I want to display a list of posts found in a blog. Blog is a class which contains Posts, an array of Post classes. To start, I created the CheckedListBox in the form designer, and I add the posts to it like this:

clbPages.Items.AddRange(_blog.Posts);

If I do nothing else, the ListBox will call the Post’s ToString() method and will display as:

Post
Post
Post
Post

We have two options for displaying this correctly:

1. Override the ToString() method. I don’t recommend doing this because ToString() is much more appropriately used in a debugging context.

2. Add a string converter: This will automatically convert each post object to a usable string when called by an object like a ListBox. ListBox uses Convert.ToString() – this uses that converter more appropriately. ToString() should only be used as a fallback.

<pre>
// Use System for the Type object
using System;
// Use ComponentModel for the TypeConvert base class
using System.ComponentModel;

namespace SiteAssistant.Blog
{
    /// <summary>
    /// Converts a post into a list-friendly string, for checkbox lists
    /// </summary>
    class PostConverter : TypeConverter
    {
        /// <summary>
        /// Indicates whether the Post can be converted to a destination type
        /// </summary>
        /// <remarks>
        /// We only support conversions to STRING at present
        /// </remarks>
        /// <param name="context"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override bool CanConvertTo(ITypeDescriptorContext context,
            Type destinationType)
        {
            if (destinationType == typeof(string))
                return true;
            else
                return base.CanConvertTo(context, destinationType);
        }

        /// <summary>
        /// Converts the post to the destination type. If the destination
        /// type is not supported, the base Conversion is applied.
        /// </summary>
        /// <remarks>
        /// We only support converting posts to strings at present.
        /// </remarks>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override object ConvertTo(ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture, object value,
            Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                string text = "";
                Post p = value as Post;
                // Ensure that the Post is not null, avoid errors
                if (null != p)
                {
                    text = p.Title;
                }
                return text;
            }
            else
            {
                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    }
}
</pre>

The code we write in .NET is like the meat inside a sandwich. The framework is the bread that wraps around our logic and keeps our application together. Our new Posts string converter will be called by the application without us needing to override the Convert function.

It doesn’t happen by magic of course. The final change we have to make is to add information about our conversion function to the posts class:

<pre>
    [System.ComponentModel.TypeConverter(typeof(PostConverter))]
    public class Post
    {
        // Rest of the code goes here
    }
</pre>

That’s all there is to it! Now we can pass a list of Posts to the CheckedListBox and manipulate each item directly. In this application, I will be using this technique to provide the Post object to the text editor with a double-click.

CSS Sanity: Remember Best Practices When Using New Tools

February 15th, 2010

Now that the rebellion against IE6 has hit mainstream, a brave new world of CSS3 and HTML5 has been opened to web professionals.

Beware Mixing Purposes
CSS is intended to define the appearance of elements, not their behaviour. Be very careful about “overloading” CSS to accomplish tasks best performed by JavaScript.

A popular example of poor CSS usage is drop-down menu lists. Some web programmers use CSS’ :hover selector to instruct the web browser to display sub-navigation when the user hovers over a list item.

ul#menu li:hover ul { display: block; }

This is much better accomplished using a touch of jQuery:

jQuery("ul#menu ul").css({display: "none"}); // For Opera
jQuery("ul#menu li").hover(function(){
jQuery(this).find('ul:first').css({visibility: "visible", display: "none"}).show(268);
},function(){
jQuery(this).find('ul:first').css({visibility: "hidden"});
});

Not only is this example less dependent on consistent web browser support for the CSS :hover selector, we’ve even thrown in a spiffy little roll-out animation.

Keep It Simple
The nth-child selector is one that stands to be abused by overzealous developers. Imagine this: change the display of every nth element as defined through an algebraic expression.

Why is this a bad thing? CSS is run in the same memory space as the general web page – that’s why it’s so fast. JavaScript tends to be isolated; meaning if you make an infinite loop in JavaScript, the web browser will eventually stop it from running. If the same thing happens in CSS, your web session is probably toast.

Separate Logic from Presentation
CSS was a leap forward because it separated presentation from structure; rather than programming font and colour elements, designers were able to explicitly control the way their web page appeared on screen. HTML was being used to serve the purpose CSS was designed to cover.

More recently, CSS has become a crutch to enable functionality better suited for JavaScript. When unsure about which to use, ask yourself: Does this solution affect only the display, or is some action happening?

iTunes – The Future, or Just a Toy?

February 6th, 2010

Following iTunes’ development has been an interesting experience. We’re moving toward a world in which physical packages of music is a thing of a past; in the meantime we’re stuck with a middling service.

My complaint goes something like this:

My wife recorded Grey’s Anatomy; when she was watching her tape the next day, she was surprised to find advertisements telling her the story from her episode was being continued in a crossover Private Practice on a different channel. Oops.

So I went on iTunes and bought her the episode she missed. $3.50 is pretty steep for a 40 minute TV show but that’s the price you pay for the convenience. After enjoying the program, my wife decided she wanted to see the rest of the season – so I bought that for her too.

When you buy a season of TV, iTunes warns you that any previously purchased episode will be downloaded again – essentially you’d be paying for it again. I can handle that – it makes sense that an item would be sold individually and part as a collection.

Two problems (both stemming from me not digging deep enough into the literature, but also totally unreasonable):
1. When I was billed for the season, I was billed individually for every episode, at the full $3.50 rate. So there was no reason to double-bill me for the episode I’d already purchased since the billing wasn’t based on a ‘full season’ – why is the system unable to correlate previous purchases and prevent the double-purchase?

2. I thought I was buying a whole season of the show – in fact I only bought the episodes that had already been released. A “Season Pass” (pay for the season and new episodes download as they become available) is something completely different… it would have been nice to have been informed of the difference.

$42 is a lot of money to pay for 11 episodes of TV. I don’t think I’ll be dropping a lot of money into iTunes when I can pay half that amount for a full season on DVD – not to mention get the benefits of hard copy, physical media.

My verdict: iTunes is an interesting model and was a fun experiment for us, but not at all cost effective. Bandwidth can be expensive, but the cost of distributing digital media is essentially $0. I would have thought TV episodes could be sold for less than $1 and still make a healthy profit for the content creators (no manufacturing costs, no distribution, no retail partners — Apple takes a cut and the rest is pure profit). What can I say, I was the one who got suckered into paying double the price for half the product.

Wamp Server Crashes Installing X-Cart

January 24th, 2010

When running a default installation, WAMP Server’s Apache crashes when installing X-Cart. The error happens immediately after setting up the MySQL tables and is caused by the curl extension in PHP.

To resolve, click on the WAMP Server icon in the task tray, go to Apache -> Version -> Get More. Download one of the 2.0 series Apache servers and install it.

Repeat the process for PHP; download one of the 5.0 series PHP versions and install it.

Switch WAMP Server to the new versions and run the install again – it should work with no problems.


SEO Powered by Platinum SEO from Techblissonline