SyntaxHighlighter

Wednesday 18 September 2024

How to write a CV

This is an old post that first appeared on the now defunct Laterooms Engineering Blog on 29th January, 2016. It's posted unedited and reflects my opinions on the subject from that time, some of those opinions have evolved, some changed and some new ones have formed. However I believe there is still value in the post, so here it is for posterity.

We're currently recruiting for new developers, and the process reminded me of something. Developers are not the best when it comes to writing CVs. Which is a shame, I'm sure we've missed some great people because their CV didn't tell us what we need to know. So I thought I'd write a little helper guide on some common mistakes developers make and some hints on writing a better CV. It might seem a little strange for someone who is recruiting to write a guide like this, but really it helps everyone. I tend to view recruiting as finding the right person, not necessarily the 'best' person. Ability to write a CV is rarely a job requirement, so by helping you, I'm also helping me.

We don't care what your old company did

A common trait I've seen on CVs is a list of all the projects a person has worked on and what the software did in the end. We want you to know what the benefits and reasons for that project are, and we want you to be able to explain that, but we don't actually care about the reasons. And one will do. We don't need a complete list.

We want to know what you did at your old company

While what the actual company does is mostly academic to us, we really want to know what you did at your last company. Tell us how you contributed to a project or product, tell us how you affected the way the company worked. Did you introduce any new tools, techniques or practises? Did you work with other team members? And how? Did you work with other parts of the business? And how did you go about this? This sort of info will give us an idea of how you would work in our company. Which is what we really want to know.

Avoid list of technologies

Recruitment companies in particular love this. A list of all the technologies you've worked with. To be honest, we are a .net shop and we will probably be more interested if you've spent 5 years doing .net than 10 years of Java. But if you've used log4net instead of NLog we really don't care. Solr vs Elasticsearch, not a problem. The right candidate can learn a new library easily, a long list of techs don't impress, they just take up valuable space. Use your CV space more effectively.

Brevity

There was a time many years ago in a company I used to work for, when recruitment meant getting a pile of over 100 CVs and having an hour to pick just 3. We were vicious, even the slightest issue meant you were sent to the junk pile. Any more than a single sheet of A4 meant immediate dumping to that pile. Things are not as extreme now but we are still busy people. Keep it brief. Anything you can't fit into 2 sides of A4 probably isn't worth saying.

Recruitment companies will ruin your CV

I don't know why, but a lot of them tend to do the opposite of many of the things I recommend in this post. They emphasise the wrong things, add stuff that isn't relevant, put their own branding on it and make it look awful. We prefer direct application for many reasons, but personally I'd much rather see an unfettered CV. This is particularly true for front end developers, if your CV looks horrible we aren't going to want to let you near the website.

Write a personal statement

Possibly the most important part of the CV, but also the bit I can give the least advice on, because it's all about you. This is where you tell us what makes you tick. Who are you? Why do you do what you do? Show your passion or your professionalism. I've invited someone to an interview based on a personal statement alone, I don't think I'd ever do that just from a job history. This is your chance to stand out amongst all the other CVs, make the most of it.

Customise your CV for the job you are applying for

In many cases you are applying to a bunch of very similar jobs, in which case you can probably skip this suggestion, however if you're thinking of a change of direction you need to think about the job you want and tailor your CV to that. For example, if you've mainly done back end development for years and are now thinking of moving to front end jobs, think about how your experience is relevant for a front end job and tell us about that.

We know people exaggerate on their CVs

This is a difficult one. Many people exaggerate on their CVs, others are not good at blowing their own trumpets. Developers tend to have a broader range of this than most people. (I think because being pedantic is an important part of our job) My advice is not to overthink it, remember we are looking for a diverse range of people, and we are usually pretty good at recognising these. Go with what feels natural to you. But don't worry if you feel you can't put "3 years experience in C#" because you have actually only been doing it for 2 years and 11 months. We are not going to discount you for that.

Link to your github/stack exchange/twitter etc account

We will Google you anyway, this will save us time, and prevent anyone with a similar name from confusing us. Also remember these are part of your public image so think of them as an extended CV.

Tell us about anything you do in the community

Events, open source etc. Communication skills are important. These are perfect examples of this, and also allow us to find out more about you very easily. However don't worry if you're not able to be involved for whatever reason, that's not a negative. There are lots of other bits of advice I can give, but these cover the most important ones. Just remember that we read your CV hoping you will be the perfect compliment to our team, and when you've written your amazing CV, send it here

Andy Lowry (Dev Lead - Search Team @azd_lowry)

Also thanks to everyone who helped with this blog post.

Wednesday 17 December 2014

First line of an email

The other day I opened my email and under "promos" this is what I saw:

(Obviously I've blanked out my address in that screenshot)

Looking at these email I noticed something. All these companies have missed an opportunity.

There are 3 pieces of information about each email displayed here. The senders name, the title, and the first line of the email. Everyone of them has chosen to use the first line for housekeeping purposes, either showing where to go to view the email in the designers intended glory, or explaining why you have received this email. These are both pretty important things to put in the email, but are they really more important than improving the likelihood of the email being opened?

A quick search on the internet suggests that it is not just Google Inbox that show the first line, in fact, it's fairly common.

So what can we do better?

Make the housekeeping stuff the second line, e.g.:

Mmmm, Captain Morgan's! Think I'll have a rum and coke!

Sunday 1 September 2013

Quantity trumps Quality?

This post was originally on my Posterous account, it's posted here without updating, some of the links my not work.

After deciding today to blog much more often, Jeff Atwood tweets about an old post of his: 


Considence I'm sure, but it rung true with a conversation I had this morning about TDD.  I'm newish to TDD, but a total convert, one thing I've learnt is not to overthink where it is leading you.  Start from the most abstract business logic and write tests for the simple cases first.  Then if your finding it difficult to write the tests try injecting in some providers or adapters instead of complicated data structures, suppling the parameters you want not what you have.  Don't be afraid to get it wrong, because your going to go back and refactor it shortly anyway.  You may find that you end up throwing away a lot, or trying things a few different ways, because you chose the wrong approach, but this quantity seems to lead to quality in the end.

Asynchronous WCF calls

This post was originally on my Posterous account, it's posted here without updating, some of the links my not work.

Update: I have created a CodeRush plugin to automate this which can be found https://bitbucket.org/azdlowry/cr_asyncwcfmethods

It is very easy to make asynchronous WCF calls without resorting to having a thread hanging around. Let's say you have a service contract like this:
[ServiceContract(Name = "MyService", Namespace = "urn:www.myurl.com/MyService/2011/06")]
public interface IMyService
{
    [OperationContract]
    MyRetunType FetchMyInformation(InfoId informationId);
}

To call this service asynchronously create another interface like this:
[ServiceContract(Name = "MyService", Namespace = "urn:www.myurl.com/MyService/2011/06")]
public interface IMyServiceAsync
{
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginFetchMyInformation(InfoId informationId, AsyncCallback callback, object state);

    MyRetunType EndFetchMyInformation(IAsyncResult asyncResult);
}

Notes:
  1. The ServiceContract's Name and Namespace arguments must be identical to the original
  2. The service only needs to implement the original interface not the new async one. WCF only uses this new interface to generate the proxy.

The new interface can now be used in the normal way the .Net 1.0 Async pattern is used, or more easily with the .Net Task Parallel Library:
IMyServiceAsync channel = GetChannel();
Task task = Task.Factory.FromAsync(channel.BeginFetchMyInformation(id, null, null), asyncResult => channel.EndFetchMyInformation(asyncResult));

Note: It is very important that the same channel is used for both the Begin and the End, otherwise WCF will throw an exception on the End.

This will start the call and return immediately. You can then either wait on the result:
MyReturnType ret = task.Result;

Or use a continuation to act on the result once the task is complete:
task.ContinueWith(task => Information = task.Result, TaskScheduler.FromCurrentSynchronizationContext());

Note: The TaskScheduler.FromCurrentSynchronizationContext() argument is optional and can be used to ensure the continuation is performed on the UI thread. Make sure this is called on the UI thread in this case, the result can be kept and reused across multiple tasks.

You can also chain async WCF calls together:
Task<string> task = Task.Factory.FromAsync(channel.BeginFetchMyInformation(id, null, null), asyncResult => channel.EndFetchMyInformation(asyncResult))
    .ContinueWith(task => Task.Factory.FromAsync(channel.BeginParse(task.Result, null, null), asyncResult => channel.EndParse(asyncResult)))
    .Unwrap();

This will give you a Task that calls FetchMyInformation, then calls Parse with the result of FetchMyInformation. The Unwrap means you get a Task instead of a Task<Task>, and allows you to easily add more continuations to the chain of tasks. I would strongly advise wrapping the Task.Factory.FromAsync calls in another method, so your code is more readable.

Task also supports exception handling, cancellation and performing multiple tasks in parallel.MSDN Task Parallel Library provides more information.

Your users do not care about your software. Deal with it!

This post was originally on my Posterous account, it's posted here without updating, some of the links my not work.

This micro-blogging lark isn't going very well, not posted anything for months.  Oh well, let's try again...

When I first started working in commercial software development (nearly 10 years ago now) the first major piece of work I was involved in was a rewrite from the ground up of one of our applications.  The application processed data in realtime and controlled some hardware based on the data received.  There had been 5 of the best people in our group working for 3 years to replace an ageing, ugly, bug riddled and almost impossible to maintain application with a shiny new one.  The old application was very basic, it was controlled through a couple of drop down menus, and some dialog boxes, and 2 text fields giving progress updates. The new one had a fancy new UI, in corporate colours with big shiny buttons that had embossed icons on them showing what they did.  Gone were the text fields, replaced with page after page of graphical displays updating in real time to show exactly what was happening.

I was lucky enough to be able to visit with one of our most important customers to oversee the install.  I installed the software and gave a demo, being sure to show off the new UI.

They hated it!

OK, hate is a strong word, they did like the new features and the better performance meant that the hardware control was more accurate (timing was very critical to this application), but they hated the UI.  It was big, took up too much of the screen, and they had to navigate around all over the place to get to the information they wanted to see.  For all it's faults the old application showed the important information, and only the important information.  This was when I realised that the customer could not care less about our software, all they wanted was their hardware doing it's job, so they could get on with theirs.

This experience has stuck with me, and guides a lot of what I do whenever I'm involved in any kind of UI work.  I've also been reminded of it by a couple of pieces of software I've had to put up with recently.  The first is this:



This is the Samsung ODD Firmware LiveUpdate, and what it does is update the firmware on a Samsung Blu-ray drive. Or should I say, what it also does is update the firmware on a Samsung Blu-ray drive, it's main purpose seems to be to sit in your task tray, popping up every day or so to remind you that there aren't any updates available at the moment.  This is for some hardware firmware!  I expect that I may have to upgrade when I first get the hardware, and then only if I have problems, I do not care even the slightest that the Samsung software guys haven't delivered a new bit of whiz bang firmware in the last 24 hours!  And look at that interface, someone has spent a lot of time and effort on that, with a lot of branding, it has an expanding black rectangle animation to let you know it's opening, and a non-rectangular window.  I'm sure they are very proud of it, but this software would have been perfectly fine as a little command line app that I can leave, hanging around on the hard disc, in case I ever need it.  It also requires that you give Samsung your contact details before it will work (or even close) which I personally think is disgusting behaviour, I've already paid you money and now you want me to give up my contact details as well. (Spamgourmet.com to the rescue)

After fighting with that monstrosity I discovered that Windows 7 doesn't support Blu-ray playback out of the box (Didn't we have this pain with DVD as well?) but the drive comes with CyberLink PowerDVD, which I installed and was able to watch my first (and possibly last, but that's another story) Blu-ray which I very much enjoyed.  After watching the film, I went to shut down my PC, and noticed a whole array of new software in my Start Menu.  When you install PowerDVD it comes with loads of other stuff you wouldn't possibly want, I mean who buys special discs that they can print labels on using the drive?  Who needs two video editing suites? Who thinks, you know, having only one way of writing a DVD isn't enough, I really need three more!

So CyberLink and Samsung haven't figured out that their users don't care about their software, but who has?  I think the perfect example of egoless software is Google Chrome.  I have to admit to being a bit of a Google fanboy, I'm blown away by almost everything they do, but Chrome is by far my favourite.  If you using it to read this, take a look at the window it's running in, now with the exception of the Task bar and the little one on the New Tab page, can you see a single Google or Chrome badge anywhere?  Notice how when you maximise it the title bar gets completely out of the way.  The whole application is designed to allow you to look at web sites, and do nothing else.  Have you ever been asked to restart Chrome or your computer to install an update? No, because it does it silently in the background, most of the time your not at all aware it's happened.

This is how all software should be, focused on allowing it's user to do what they want to do with the minimal of fuss, that's all they are really interested in, and that's what they pay for.

Task Parallel Library equivalent of Thread.Sleep()

This post was originally on my Posterous account, it's posted here without updating, some of the links my not work.

Recently I had need to use Thread.Sleep() inside a TPL Task.  Thread.Sleep is usually something I avoid but I was testing out a theory and Sleep was my "long running process".  However I also needed this to scale to 50-60 tasks running in parallel, and Sleep was wasting an entire thread that could be better served doing real work.
So I needed a solution that would cause a Sleep task, that returned the thread back to the thread pool while it was sleeping.  Some searches on the net didn't find much but it turns out to be pretty easy.  Here is the solution I eventually settled on:
    public class TimerTask
    {
        public static Task Wait(int millisecondsToWait)
        {
            var tcs = new TaskCompletionSource<object>();
 
            var timer = new System.Threading.Timer(delegate(object obj)
                                                   {
                                                       tcs.SetResult(null);
                                                   },
                null, millisecondsToWait, System.Threading.Timeout.Infinite);
 
            Task<object> waitTask = tcs.Task;
            waitTask.ContinueWith(antecedant => timer.Dispose());
            return waitTask;
        }
    }
Hopefully someone else will find this useful.
Note: I think there might be an issue with Timer resources running out if a very large number of these are in use at the same time, but I havn't seen this in practise.

Supporting Multiple Threads in Moq


This post was originally on my Posterous account, it's posted here without updating, some of the links my not work.

I'm a big fan of the Moq library.  It provides a really simple way of introducing mock objects into unit tests.  However recently we stumbled onto an issue with it.  The mocks that are produced are not thread safe.

 (See this issue)

Purests would say this isn't an issue as you shouldn't have threads in your unit tests, and this is a position I generally do agree with, however there is always some code to manage to multiple threads and that should be unit tested just as much as all the other code.

The issue has existed for a while and a colleague of mine has also created a fix, but the fix isn't in a released version and we didn't really want to go to the trouble of building Moq ourselves just for the one failng unit test.
One solution to this, is to make use of the same features Moq is built with.  Moq uses the Castle DynamicProxy library which is usually ILMerge'd with the Mod.dll assembly, but Moq also comes as a version without DynamicProxy merged in.  By switching to this version and using DynamicProxy ourselves we can do this:

public class SynchronizedInterceptor : IInterceptor
{
    private object lockObject = new object();

    public void Intercept(IInvocation invocation)
    {
        lock (lockObject)
        {
            invocation.Proceed();
        }
    }
}

public static class MoqSynchronisedExtensions
{
    private static readonly ProxyGenerator _generator = new ProxyGenerator();

    public static TType GetSynchronizedObject<TType>(this Mock<TType> mock) where TType : class
    {
        var synchronizedObject = _generator.CreateInterfaceProxyWithTarget<TType>(mock.Object, new SynchronizedInterceptor());
        return synchronizedObject;
    }
}

This allows to write this unit test:

[TestMethod]
public void Moq_WhenUsingSynchronizedObject_IsThreadSafe()
{
    // Arrange
    var m = new Mock<idisposable>();
    var disposeable = m.GetSynchronizedObject();

    // Act
    Parallel.For(0, 1000000, d =>
    {
        disposeable.Dispose();
        disposeable.Dispose();
        disposeable.Dispose();
        disposeable.Dispose();
        disposeable.Dispose();
        disposeable.Dispose();
        disposeable.Dispose();
        disposeable.Dispose();
    });
}
With this solution we are able to get our unit test to pass every time, without affecting any other tests, using a manual mock or resorting to our own version on Moq.

This solution might not work for everyone, GetSynchronizedObject() returns a new object every time, therefore it is only synchronized when accessed though that object.  Also if you are doing other synchronization in callbacks you may introduce deadlocks into your unit tests.

This should make a good stop gap if you are experiencing this issue until there is an official fix built into Moq.