Steve Job’s Commencement Address Still Holds Up

If you haven’t seen this already, I definitely recommend you spend 16 minutes of your day listening to this video of Steve Job’s commencement speech.

This is a college graduation commencement speech Jobs gave back in 2005. In it he talks a lot about his early life and how some seemingly small decisions he made ended up making a huge impact on his later life – including his life and work at Apple.

For folks currently in school, or contemplating what to study/do with their life, this video is really perfect for you:

Do Harder, Longer and more Complex Interviews find better Candidates?

I read Reddit regularly, as apparently half the world does. One of the subreddits I follow is the ExperiencedDevs subreddit because sometimes I learn something or find an interesting article there.

Today I saw this post and it struck a chord:

In my experience the answer is NO. Not just no – but NO with capital letters because it is that serious.

Software Interviewing is Broken

I’ve done hundreds of interviews in my career and I’ve hired dozens. I can remember 2 bad hires that should have been caught in the interview process.. One of those was someone who we gave a job as he was desperate. The other one who was a young recent college grad who found a better job and ghosted us. I accept blame for the first but not the second.

I’ve never used a coding test as part of my hiring process.

Ideally, I’d like to see some past work and code. Typically a technical screen will be 2-3 people asking questions. That’s pretty much all that’s required. We’re talking 2-3 hours tops and you know or don’t know if the person is a good hire. That’s all it takes.

Yet, somehow the software industry has gone the way of high schools. For some reason we now have more and more steps to get through and more and more tests. As if tests somehow prove someone is a developer. Some interview processes are a 4-6 step process over weeks or months. I’ve done interviews where they expect you to complete a 8-20 hour long assignment and turn it in.

These tests are a huge waste of time. They keep candidates from applying. (Who has time to waste on such nonsense?). Plus, these tests weed out a ton of great candidates.

Tests Suck

Let’s talk about tests for a second, because really, that is what so much of software interviewing has become. Almost every interview now consists of some kind of coding test and sometimes even multiple coding tests. Sometimes you’ll run into personality tests, IQ tests or a CCAT test. There is a whole cottage industry now that provides tests for companies looking to hire and another whole industry providing practice problems and tests for software interview tests. LeetCode.com is one of the best sites for practicing interview problems.

That’s all well and good except tests SUCK.

Tests are artificial, contrived and often poorly constructed. Passing or failing a potential hire on a 1 to X hour long software test is stupid. Even if its longer or a whole day test, it is still pretty much useless.

Why?

In your test, how much are you testing someone’s skill with a particular framework, tool or library vs their ability to learn, collaborate and produce great code? What if your hire has been doing Ruby for 10 years and your test is using some new Gem that he’s never used or he used once 6 years ago? So you’re going to pass on someone who spent half the 1 hour test learning about the framework? Unfortunately that is exactly what most companies do.

Lets Think for a Second

Students in school study for the test and not for the material. For examples you don’t have to look very far. We have the SAT, ACT or <insert your state> standardized tests in just about every state of the country. Students spend a ton of time practicing and preparing for the test itself. In some states, the last month or more of a school year is spent ONLY preparing for standardized tests. During this time students are not actually learning, they are just getting better at the test.

Now in the software industry, we’re doing the exact same stupid thing.

Hiring companies are requiring these waste of time coding tests and failing the vast majority of their candidates. So, in response candidates now look online before they apply or after they hear they will need to take a test. They will find out exactly what coding test you use and prepare. (For almost any large tech company, the entire hiring process is available online, including what tests they use.)

Even if your a small company and your interview process is not public knowledge – once you tell the candidate what test you use they will find the answers online. It is not hard. So, they look great on your test and pass. Except – really, they “cheated” because they knew what was coming, prepared and did well. Thus the test provided nothing and you let through a candidate who can pass a test where they already know the answers.

Best case as the hiring company, your candidate didn’t already know about the test so its a “surprise” and they haven’t already seen it. So they have to take it live and complete it in the time given. (As the hiring company you will never really know this by the way.)

So where do we go from here?

Let’s say the candidate passes. Great, they move on to the next step. If they fail, you boot them.

What if though, the person who failed was brilliant but didn’t know your specific library? Or they had an urgent phone call during the timed test they had to take? Possibly the test tool had an issue? Or maybe the candidate was nervous and didn’t do well? Could it be you’re looking at something like structure and your structure expectation is different from what they did. I could think of a thousand reasons you might not like their test result.

In all of those cases, you’d never know how good the candidate was because you just booted them based on a test result. You could have booted a great developer who had a bad day or a bad few hours. Or maybe your test sucks and you need to re-look at it. You will never know – and that is the whole point: the test proves nothing.

Let’s look at the different cases:

Do Tests Work?

Checkout this table. Along the top we have columns showing whether or not the candidate knew the test ahead of time, and along the side we have rows for whether or not the candidate passes:

Candidate DID know the Test Ahead of TimeCandidate DID NOT know the Test Ahead of Time
Candidate Passes– So, they cheated? Or do we call that prepared?

– Or they are just really good at the test?

– Or are they actually a good dev and the test proves it?
– Great, so I guess they know the tech we tested on?

– Or they found the answers online as they did it…

– Or are they actually a good dev and the test proves it?
Candidate Fails– Did they have a bad day and do poorly?

– Did they study an old test version and miss some small change?

– Do they not know the libraries you were using or testing?

– Or maybe your test sucks?

– Or maybe they are a bad developer?
– Did they have a bad day and do poorly?

– Do they not know the libraries you were using or testing?

– Did the test software crash or break?

– Or maybe your test sucks?

– Or maybe they are a bad developer?

In each case, we really don’t know if the developer is good or bad. We just know they passed or failed a test. But we don’t know why. This is a pretty bad way to figure out if someone should be hired or not. Yet this is all too common.

So What is Better?

Every company, team and project is unique. So, there isn’t a perfect one size fits all approach. But, I can tell you what has worked very well for me over the years. The following steps lay out the process in detail:

Hiring Step 1: Job Post Instructions

Obviously you will have a job posted up online in various locations. When writing your job description, include at least 1 or preferably 2 specific instructions for candidates. For example:

  1. Send your resume to <x> with the subject line <y>
  2. Please include a brief paragraph describing your most recent use of <z> technology

These are simple instructions that anyone who reads your job post will follow. Right?

So what’s the point then?

Most applicants don’t really read the job post in detail. They see a headline like “JavaScript Developer” for a job post, think “Hey I know JavaScript” and apply. People like this with no attention to detail will get weeded out right away. This will get rid of at least 50% of your candidates.

Hiring Step 2: Quality Screening

The next step in the process of hiring is quality screening candidates.

Hopefully you now have a nice collection of resumes from people who made it through the initial screening we did in Step 1 “ie. Can you follow instructions”. Now, we need to do some screening of candidates. For this stage I do a quick review of their resume, application and cover letter.

My goal in this stage is to quickly remove non-qualified and unlikely to succeed candidates. I am looking for obvious problems such as:

  • Obvious typos or other boneheaded errors in the resume
  • Obvious lack of knowledge or experience in required technologies
  • Large or unexplained gaps in employment
  • Changing jobs too frequently
  • Deception

The last bullet point above – Deception – I think warrants some additional comments. A lot of folks exaggerate a bit on their resume. That’s not what we’re going for here, though that can be a problem. You won’t necessarily know if they are exaggerating at this point just from reviewing a resume.

Deception is not always easy to spot. But there are some telltale things I look for:

  • Abbreviated Names: Yes, really, this is a problem. A LOT of less scrupulous head hunters will submit fake resumes under names like A. Jones. The game they play is that they hope you like the resume, reply back and then they can pitch you on their great placement services that provide cheap talent for a small fee of $20000. Yes, this really happens. How do you avoid this gotcha in your resume? Put your full first and last name on there.
  • Dates Don’t Add Up: I have seen a lot of resumes over the years claiming way more years of experience than someone has. If you are 2 years out of school, chances are you don’t have 8 years of professional Java experience, for example.
  • Resume does not match Linked In: When I see resumes from promising candidates I look at their LinkedIn and other social media accounts. When their resume is quite a bit different than the info they post on LinkedIn for jobs and experience, that is a big red flag.

Those are the most common deceptions I find in resumes. Anything I consider deceptive gets tossed. If the resume still looks promising it gets added to a list of folks we would try to phone screen.

Hiring Step 3: Initial Phone Screen

What I do here is probably pretty typical for this part of the hiring process.

The goal of the initial phone screen is to check for 3 things: communication skills, personality fit, basic technical competence. This phone call is usually 15-20 minutes and is very casual. Typically during this call I will introduce myself, talk about the open position and then ask the candidate to talk about themselves, the experience they have and why they are a great fit for the role.

If the candidate is impressive, I will advance them to the next level. If the candidate is only good, then we hold them but do not advance them further. Every other candidate is discarded.

Hiring Step 4: Technical Interview

The next step is to invite the most promising candidates to a full technical interview. I like doing these in person, but remote works as well. For these I like to set aside at least an hour, but 2 is better. I also like to have a committee of 3 people on the hiring side on the call. The ideal mix would be the candidate’s manager should they be hired, and 2 technical resources.

In this technical interview, we ask pointed questions about the candidates technical history.

What we’re most focused on is understanding what the candidate has actually done. This is an important distinction. Just because candidates were on a team that did something does not mean they actually contributed in a meaningful way.

To help understand a candidate’s actual work I ask them what they are working on. Some will say “I am part of team X that is building Y”. OK, that’s fine but I want the candidate to tell me what exactly you are doing on the team. I will drill down deep into the details as far as they can go. The more they can tell me about what they are working on the better. Specific things I like to hear about include:

  • What the purpose of the software you are building?
  • What is the system architecture?
  • What tools are you using?
  • What are the pros and cons of the system?
  • What specific components have you worked on and what did you build?

I also like to ask some more general questions:

  • What is the biggest mistake you have made? How did you handle it?
  • If you were to build a new system today, what would you use and why?
  • What technologies do you love / hate and why?
  • What was the last technology you learned? Why did you learn it.

For these general questions, I’m looking to learn about the candidates experience and thought process. If they can explain their choices well, that is a great sign and what we’re looking for. If they can’t that is a big red flag.

At the conclusion of the interview, we hold a small conference with the 3 interviewers. A unanimous yes will result in us making an offer to the candidate. Anything less is a no and we reject the candidate.

Conclusion

Hiring technical staff is hard. But there are ways to find great people.

We need to remember that great people is what we’re looking for. We’re not looking for just a skill – we’re looking for people we will work with, train, grow and hopefully people who will buy into the vision of your company.

I’m Officially a Patented Inventor!

I love building new things, and coming up with new ideas. The ability to create new products and solutions has always been great fun. One of the things I wanted to do since early in my career was to have a patent in my name.

At my first professional software job at Kodak back in 1997, I remember closely working with a lot of really brilliant engineers. One engineer in our team who’s name I sadly cannot remember had over 100 patents issued. His entire job was to come up with radical new ideas and see if he could make them work. He had no other responsibilities which at that time was quite rare. At the time I thought it was pretty incredible that was his only job. Since then, I always wanted to be a patented inventor.

Well, today I can say that I am officially a patented inventor!

So What is the Invention?

During my work at Pleiotek, I was a co-inventor on a series of ideas that resulted in Patent 10786395: “Apparatus for Processing Healthcare Data and Storing and Transmitting Large Amounts of Data via a Bandage or Sticker”. Yeah that doesn’t roll of the tongue I know.

In short, this patent captures the idea behind storing patient medical data on the patient itself. Imagine a soldier injured in a battle, or someone hurt in a mass protest. In these urgent and tense situations, timely patient care is critical. But in these types of scenarios, the patient will need to be made safe, and ultimately moved to higher echelons of care.

We must retain records of patient injuries and care. Incorrect or incomplete patient records can cause mistakes. For example, a patient in pain may be administered a dose of morphine. Morphine can be fatal in high doses. So it is critical that providers know if a patient has already received the medication.

The current state of the art for tracking patient data in these situations is weak. Patient data is written on very small cards, or on the patient via sharpie. Yes really. In some cases mobile devices are used to track data, but it is rare in the theatre of war or in mass casualty situations.

The system that we invented helps care givers both track medical data and provides a way for the data to easily travel with the patient. We invented various techniques for embedding data storage in bandages or very small patient worn devices. This allows care givers to record the patient’s medical information directly on the smart bandage or device on the patient. Now patient data follows the patient wherever they go. This ensures their medical record is complete and accurate. It also ensures care providers have all the information they need to provide the best care.

The idea and technology is great. Although I am no longer part of Pleiotek, I am hopeful that they can bring this technology to market. This idea can be a great help to our military as they treat soldiers who sustain non-combat or battle injuries. It will also help our local emergency healthcare teams as they treat large events with lots of patients and hand offs between providers.

The Power of PseudoCode

“Pseudocode” is a powerful way to write and document software. Put simply Pseudocode is just plain english text describing what the code should do – it is not actually code itself. I found this old-school screen cap on Google that describes nicely a few of the reasons why Pseudocode is great:

How to Write Pseudocode: 15 Steps (with Pictures) - wikiHow

The following is an example of what a good use of Pseudocode looks like. In this case I’ve written out the basics of a function to handle user logins:

/**
* login:
* 
* The purpose of this function is to attempt to login a user.
*
* Returns: 
* User record: On successful login or
* false: On error or failed login
*/
function login(username, password) 
{
    // TODO: Check for valid inputs to this function:

    // TODO: Get the user from the database:

    // TODO: Check the user is valid:

    // TODO: Check the user is not locked out:

    // TODO: Validate the user's password:

    // TODO: If the user passes all above checks and has a valid
    // password, then return their user record, otherwise 
    // return false:
}

As you can see we haven’t written real code. We really only wrote the skeleton of a function and then wrote out in plain english comments what our code will do.

The Benefits of Pseudocode

Why would you write out Pseudocode instead of just writing the code? Well there are a few reasons:

  1. Breaking Down the Problem: By writing out the basic steps to implement our function we have to think about the entire problem to be solved by the function. This helps us break down how the code should work and how it must work when there is bad input or an error.
  2. Specify the Interface: Pseudocode can help us to define the input and output of our function, class or code blocks. In the case of the example above we have to handle two cases – a successful login and a failed login, so we need to have returns for both. It also allows us to share our planned interface with other developers before we have written the code.
  3. Identify Opportunities for Reuse: For each of the high level steps of the function, we have a TODO line. In some cases we can identify through these steps items that could be made separate functions that could be reused. In the case of this example, there are at least 3 items that should be separate reusable functions.
  4. Find Gaps in Understanding: The final benefit of Pseudocode is that it can help you determine what you need to know that you don’t know right now. In our hypothetical example, after writing out the function it is clear we don’t really have a strategy for error handling and that needs to be addressed. Returning “false” when a login fails is OK – but does not communicate errors, or reasons why a user could not login. We won’t address it here, but proper error handling is definitely a topic for the future.

Actually Writing the Code

Taking into consideration our four points above we can actually write out or code by filling in the TODOs. We will do this with some basic operations and calls to external functions/libraries we either write or have available:

/**
* login_v2:
* 
* The purpose of this function is to attempt to login a user. 
* We've made some changes based on our thoughts so far.
*
* Returns: 
* User record: On successful login or
* false: On error or failed login
*/
async function login_v2(username, password) 
{
    // ------------------------------------------------------ 
    // Check for valid inputs to this function. 
    // ------------------------------------------------------ 
    if ((username != undefined) && (username != '') && 
        (password != undefined) && (password != ''))
    {
        return false;
    }

    // ------------------------------------------------------ 
    // Get the user from the database - this should be
    // a reusable function:
    // ------------------------------------------------------ 
    var the_user = await users_service.get_user_by_username(username);

    // ------------------------------------------------------ 
    // Check the user is valid and is not locked out:
    // ------------------------------------------------------ 
    if (the_user == undefined || the_user['status'] != 'VALID')
    {
        return false;
    } 

    // ------------------------------------------------------ 
    // Validate the user's password:
    // ------------------------------------------------------ 
    var valid_password = await users_service.validate_password(the_user['password'], password);

    // ------------------------------------------------------ 
    // If the user passes all above checks and has a
    // valid password, then return their user record, 
    // otherwise return false:
    // ------------------------------------------------------ 
    if (valid_password == true)
    {
        return the_user;
    }
    else
    {
        return false;
    }
}

A lot changed between our initial Pseudocode and what we have now. But, the key take away is that the code we added just filled in the pieces we created with our Pseudocode.

Creating/Using Reusable Functions

Most of the above is pretty simple code. It may or not be an optimal solution or example, but it is instructive. One key concept shown in this example is how Pseudocode can help you identify reusable code.

The “users_service” is an example of what I mentioned above. Pseudocode helps you find places where you will need to do something in other places – and the user operations in this function are exactly that. You will need to get user records frequently so write the code to do it once and reuse it. Similarly password checks may need to be used in multiple places, so write it once and reuse it.

Often times when I build code, I will define services to handle various pieces of functionality. One very common one I use is a “users_service” that handles all user operations – get, create, update, delete, search, and validate operations will all be part of the service.

Finding these places where you will want to create reuse-able code is one of the strong benefits of the exercise of Pseudocode. It will become very clear when you go through what code will be something you would want just here in this function vs. something you can use over and over.

Added Benefit: Code Documentation

Another great benefit of writing Pseudocode first before you write code is now you have code documentation already written. It’s already written as part of your Pseudocode. You just need to tweak it to match the actual code you have written as needed.

Some may say that the comments above are trivial and unneeded. To some extent that is true, but in this case we’re providing a simple example so the comments help.

Self Documenting Code is a LIE

I hold the VERY STRONG opinion that code comments are required and you can never have too many code comments.

I absolutely HATE the idea that code is “self documenting”. It’s not. Stop lying to yourself and your team.

Let me repeat myself. Your code is NOT self documenting. You, the original author of the code may have a complete understanding of it at the time. You or the poor bastard that comes behind you 18 months later will have no clue what you meant or what business rules you were using.

(Note: I’m not the only one who thinks this by any stretch. Here is another great article on the topic: https://medium.com/it-dead-inside/self-documenting-code-is-mostly-nonsense-1de5f593810f)

I’ve seen and had to work on code that is more than 10 years old many times. I’m talking about code running enterprise applications at billion dollar companies. Very rarely do these ancient applications have any code comments.

The worst example I can think of was a 21 year old PHP applicaiton. This code was initially written 5 major PHP versions ago. It has been heavily tweaked, changed, and refactored over the years. No one ever added code comments and so no one knows how it really works. Working on new functionality or making bug fixes takes forever because you have to read through a ton of code to figure out what is even going on.

This is the nightmare you create without code comments. Nightmares for whoever the poor bastard is that has to work on your code down the road. That poor bastard might be you by the way.

But by writing Pseudocode first, you already have a basis for code documentation and code comments. So, I advise that you do so, and continue to comment your code as it grows and evolves. You will thank me later. Your colleagues and folks who come behind you will thank you too.

Start Today

If you don’t already make a habit of writing out code in Pseudocode – try it out today, or the next time you are writing code. It will help you better understand and structure your code – plus it comes with the added benefit of having already written code comments to help you and any future developers who have to touch your code.