A better way to describe “on the bench” and “non-productive”

I just heard my wife, a corporate accountant, on a call with her team talking about people in the construction company she works for charging time to projects when they are non-productive (during this time of COVID-19 and working from home).

This is a similar situation to working in IT corporate consulting, where the consultants generally describe time back in head office between client projects as being on the bench. It’s a strange situation to be in – no fault of the employee but it holds a burden and shame many carry internally.

The great thing I heard my wife say was:

Let’s not use the word “non-productive”. Let’s use the word “non-recoverable“.

The words “on the bench” and “non productive” carry a negative connotation and place the focus (blame?) on the employee.

“Non-recoverable” or “non chargeable” on the other hand describe the situation just a well, better reflect it in business terms, and remove the negative inference on the employee.

It’s not like employees are ever without work to do (or things to learn).
The only difference between types of work is whether or not the business is directly charging a client for that slice of time.

Coding Challenges and Technical Tests When Applying for Jobs

Today, someone I’ve never met, whose name I don’t know, rated and told me I’m not a good software developer.

It wasn’t someone on Twitter or social media. It wasn’t an industry expert.

No, it was feedback I received from coding challenge I did for a job application.

As a general rule I refuse all technical tests and code challenges (even if it means not being able to apply for a job).
I’m not sure why I took this challenge. I guess I let my better judgement slip.

Coding tests in job applications have their place, but having been on both sides of the table (and I’ve never made some do a test) they’re more for assessing entry level developers than people nearing 2 decades of in-the-trenches experience.

 

In this post I want to share my thoughts on the process I went though by using the actual test, sharing my solution and the exact feedback I gave the recruiter I went through.

I’m not name dropping the particular company that required the test. But, their requirements are in a public GitHub repository.
I don’t know the department, team or people I was applying for (there’s a warning sign for you) so I can’t name drop individuals.
I also didn’t sign a waiver with the company against sharing my experience.

To be clear: This is not an attack on any one person or the organisation. I’ve been through almost exactly this instance multiple other times in the past.
This instance simply provides a perfect example to share.

 

One final thing: this was for just a 4 month contact. I’ve done a lot of contracting over the years and have never been asked to perform a code challenge.

This whole situation says a number of things to me about:

  1. The persona assessing me (I can infer their experience as well as their personal motivations).
  2. What the organisation is potentially looking for,
  3. Laziness in the organisation’s recruitment process. Say what you want about “efficiency” in hiring, but this speaks to laziness.
  4. Recruiters are still not doing their job in terms of understanding their industry; understanding the people they represent; educating their hiring clients.

 

The Code Challenge Requirements

The complete requirements of the code challenge were provided via a link to a public GitHub repository at https://github.com/medibank-digital/coding. I’ve also included it below.

 

# Medibank Coding Challenge

## Overview

A web service has been setup at the following URL: 
-	https://gist.githubusercontent.com/medibank-digital/a1fc81a93200a7b9d5f8b7eae0fac6f8/raw/de10a4fcf717e6c431e88c965072c784808fd6b2/people.json

## Requirements
You need to:
- Write some code to consume the json hosted on the above web service.
- Output a list of all the cats in alphabetical order under a heading of the gender of their owner.
- Output must be presentable on a web browser.
- Submissions will only be accepted via GitHub or Bitbucket.

Please note:
- It can be written in any language you like.
- Use any libraries/frameworks/SDKs you choose.
- Use industry best practices.
- Use the code to showcase your skill and what you value in a software application.

## Example

```
Male

Angel
Molly
Tigger


Female

Gizmo
Jasper
Notes

```

2 things immediately came to mind:

  1. Use industry best practices” is a MASSIVE alarm bell for me.
    For 2 reasons:
    a) there is no such thing as “industry best practice” in software development. Developers like to use that phrase but in reality it doesn’t exist and we all know it.
    b) What it really says is “some person wants you to write the specific style of code and architecture that they think is best, and we’re not going to tell you what it is”.
  2. There’s no guidance in terms of what they are looking for.
    Do I need to create a full app?
    Can I create just a helper?
    Are there code standards they’re looking for (and what are they)?
    Are they interested in UI design?
    What if I’ve written it in a language they don’t use?
    What if I wrote it in a language they couldn’t compile and run (they did say “It can be written in any language you like”)?
    Ultimately: how does this represent what they are looking for in the work the candidate will do on the job?
    And what the fuck is the actual goal of this test anyway?

 

The people.json file contained the following:

[
  {
    "name": "Bob",
    "gender": "Male",
    "age": 23,
    "pets": [{"name": "Garfield", "type": "Cat"}, {"name": "Fido", "type": "Dog"}]
  },
  {"name": "Jennifer", "gender": "Female", "age": 18, "pets": [{"name": "Garfield", "type": "Cat"}]},
  {"name": "Steve", "gender": "Male", "age": 45, "pets": null},
  {
    "name": "Fred",
    "gender": "Male",
    "age": 40,
    "pets": [
      {"name": "Tom", "type": "Cat"},
      {"name": "Max", "type": "Cat"},
      {"name": "Sam", "type": "Dog"},
      {"name": "Jim", "type": "Cat"}
    ]
  },
  {"name": "Samantha", "gender": "Female", "age": 40, "pets": [{"name": "Tabby", "type": "Cat"}]},
  {
    "name": "Alice",
    "gender": "Female",
    "age": 64,
    "pets": [{"name": "Simba", "type": "Cat"}, {"name": "Nemo", "type": "Fish"}]
  }
]

 

My Solution

I completed my solution in using React (it was good to practice for something I’m currently learning) and I published it to a public GitHub repository at https://github.com/jsnelders/medibank-coding-challenge.

All up it took me about 4-ish hours. I actually started it while watching TV the night I received the request and finished it the next morning between other tasks. In all I think it was about 4 hours of my time.

Now, that may seem like a lot of time for a simple task like this, and I’m sure there are better programmers than me that can spit it out in half the time or less, but consider the following:

  1. I had to guess at the “hidden” agenda and requirements they were assessing me against. So, I have to spend a bit of time trying to get inside their heads.
  2. It’s a complete React app. Even with create-react-app it still takes time to build one.
  3. I’m new to React and only just [finally] getting into ES2015, so I spent some time with reference material open.
  4. I’ve never worked with the Jest test framework.
  5. I’m an OG developer trying to keep up with “modern” ways of development. In this case, converting my old school (by which I mean more than 5 years) approach to programming JavaScript and use ES2015 approaches. Which, is no more “correct” or “better” than the old way.

 

The Feedback

The feedback I received via the recruiter is exactly as follows:

Here is some further feedback for you.

Positive

    • Used ES6 filter method for sorting list
    • Used config file for url

Negative

    • Didn’t break up React components (one for entire app)
    • Very long methods instead of breaking logic up into smaller chunks
    • Could have used constants for JSON response types instead of repeating string literals throughout class
    • Many of the ‘let’s could have been ‘const’
    • Had a unit test but when try to execute it had a syntax error, so couldn’t execute
    • Inconsistent and Unconventional naming conventions (didn’t use service, utility, some declared with lower case others, while other upper case)

 

To which I replied:

 

Thanks [name],
This is exactly the sort of feedback I was expecting.
I’m all for constructive feedback, but to be honest this is not constructive. If anything it’s nitpicking and disrespectful of candidates because we have to invest at least half a day of our time and can’t even get a reasonable response.
I’ve included in my own thoughts in red beside the feedback. You don’t need to pass it on – it’s for you do understand how a candidate can see this situation.
I just want to reiterate what I mentioned on the phone from a candidate’s point of view:
* A company can’t throw such “small” tests like this at developers without giving at least some context of what they’re looking for. That’s a hostile action, and leaves a candidate unsure of what to focus on and how far to go. How I would approach in a larger enterprise software project is very different to a small “toy” case like this.
* It’s unreasonable to expect candidates to invest hours of their time (ie. a test like this takes a minimum 2-4 hours) and not discuss the results. The comments provided are “not” feedback – they’re just someone’s opinion without explanation.
So it makes me as a candidate ask: Is this how they operate as a team and treat developers? Is their work style and priority to pick on coding style or solve business problems? Would I go into that team and worry every day that all my code reviews are going to be picked on, without standards given, and how would I feel?
Those are the serious questions that come to mind when I apply for a job and (without an interview) have my ability as an experienced developer scrutinised and “picked on” by someone I’ve never met, based on criteria I haven’t been told.
It is honestly an experience that does not leave me feeling good, especially considering we work in an industry where most us – even the best and most famous – still talk about feeling “imposter syndrome” after 20+ years.
Apologies – I don’t want this to sound like a rant, but I do like to give an honest point of view on the testing process to recruiters whenever I can, especially having sat on both sides of the hiring table.
Cheers,
Jason

 

And my responses to the Positive and Negative Feedback:

 

Positive

    • Used ES6 filter method for sorting list [I only did this because I exepcted that’s what they were looking for. A loop is still a perfectly reasonable option too.]
    • Used config file for url

Negative

    • Didn’t break up React components (one for entire app) [Not required on an application of suck low complexity. This should have been stated as something they were looking for.]
    • Very long methods instead of breaking logic up into smaller chunks [Which method are they referring to. I’ve checked all my code and I just can’t see a function I would think necessitates chunking or shortening.]
    • Could have used constants for JSON response types instead of repeating string literals throughout class [Not even sure exactly which code this referring to? If I was to guess, then I’d say I understand their thinking but don’t think it’s reasonable without pre-defining it as a coding standard they use (what I did was “not” unreasonable and would cause not maintenance problems).]
    • Many of the ‘let’s could have been ‘const’ [I’ll concede this “to a very small degree”, bit this is really low-level nitpicking. Both are perfectly valid, and no dev who’s been working front-end web more than 5 years would even consider this a problem.]
    • Had a unit test but when try to execute it had a syntax error, so couldn’t execute [Fair enough. I must have renamed a function and not re-run the test. And technically, it’s not a “synatx” error.]
    • Inconsistent and Unconventional naming conventions (didn’t use service, utility, some declared with lower case others, while other upper case) [I totally disagree (and just saying this one line is not enough feedback). In fact, I used conventions I’ve just learnt that are taught by one of the industry leading teachers of React! And they didn’t set any expected conventions (there is no single one in our industry).]

 

My Thoughts

I’m an very experienced developer. No boasting – that’s just how it is. Almost 20 years in the industry. Many roles. Over 8 languages and variants. I’ve worked with countless different tools, technologies, platforms, patterns, and code from probably hundreds of other developers.

I’m also still a programming software developer after almost 2 decades on the jobs. The number of people with more than 15 years in the industry who can say that is a dwindling number.
I’ve done everything from code Excel to website interfaces, setup and manage deployments to debug production issues, hire and manage staff to run a business.

What that means is I’ve seen and experienced a lot, in an industry that has no certification and governing bodies, and the only thing I can tell you is: there’s no right or wrong way to do things – just someone’s opinion.

All that said, I’m an “average” programmer.I know that. I get shit done and solve business problems – that’s my job. I’ve been through the school of hard knocks more than once in life. And this not the first time I’ve received feedback like this on a coding challenge (most times I never received feedback).

Even so, it’s still a kick to the stomach to be criticised like this, from someone I’ve never met, without a chance for discussion, which is what you would reasonably expect in an actual workplace.

I’ve had exactly one decent technical test in my career as an interviewee. It was about 10-15 lines of  JavaScript printed on a piece of paper. Handed to me during the interview and I was asked to describe how it worked. Speak it out aloud. No right or wrong answers. And we discussed it as we went. 5 minutes taking across a table. I missed something and we discussed it.

That’s how you test someone.

SMaRT Code Architecture

I’ve been thinking about code architecture in consumer grade software solutions and what I believe matters most.

As a result I came up with:

SMaRT Code Architecture

Which stands for Simple. Maintainable. Readable. Testable.

 

Simple: It’s easy to find (discover), understand and trace code during debugging and or enhancements. The simplest code is no code. Not always feasible. But reducing layers and reducing decomposition can help.

Maintainable: Developers should be able to (and not scared to) fix bugs and introduce enhancements. An unmaintained system suffers from entropy and can become “toxic” within the larger ecosystem.

Readable: Code is written for people to read, not computers. Everyone should be able to easily read and understand the code you wrote yesterday – from a 1st year novice to a 20 year veteran. Fancy or shorthand code works against the next person. Use white space. Write comments to assist in understanding intent. Old school statements are still valid.

Testable: Developers need to easily test their changes. If they cannot there is a lower likelihood of changes being made, and a higher chance of errors when they are.

 

Notice I haven’t mentioned anything about patterns or practices, APIs or languages features. Those are implementation details – how you implement as opposed to what is important.

What is important is code that makes it easy for people in the future to learn and touch the system.

Learning React.js and practising in StackBlitz (online IDE)

How easy is it to learn React and practise at the same time?

  1. Start with this course on Pluralsight (https://app.pluralsight.com/library/courses/react-fundamentals-update/table-of-contents).
    Can’t afford Pluralsight (it is expensive for many developers)? You should be able to find something on freeCodeCamp or YouTube (search for something like “React fundamentals or “Learn React”).
  2. Create a GitHub account (every developer should have one for their work and portfolio).
  3. Create an account on StackBlitz – a Visual Studio Code “in the browser” development environment – and link it to your GitHub account so you can start committing (saving) your work as you go.

See the project I’m building as I learn React at https://stackblitz.com/edit/test-react-playground/ (GitHub repo https://github.com/jsnelders/test-react-playground).

Designing for colour. Computer screens lie.

I’m putting together a new website today and implemented the classic web developer test: I set a background color of red on a div to check my build system was refreshing.

It worked. But with an odd side effect.

The red I saw looked pink on one screen (my laptop screen, in fact) and different shades of red-ish on my other 2 screens.

I have a 3-display setup at home – my laptop screen with 2 connected monitors on either side. I also run an application called F.lux all the time which essentially sets a night light (reduces blue light and runs a softer colour). But even with that turned off I still had colour variations across all three screens.

Unfortunately I couldn’t take a good enough picture to show the contrast clearly, but hopefully the following 2 photos give some idea:

 

Regardless, the moral of this story is:

No matter how precisely you design the colour of software or websites to look, there is no guarantee users will see what you expect them to see.

Keep your designs simple, focus on contrast and hope for the best.

And remember, there’s always grey scale to fall back on.

The responsibility of a software developer is to “deliver stakeholder value”

The responsibility of a software developer is to “deliver stakeholder value”.

 

Stakeholders are people and business.

We are tasked with creating things that provide positive value to those who commission it (the business) and use it (the customer).

Our responsibility and priorities are the following 3 tenents of software development:

Security: Ensuring the software we develop does not harm the business or customer, either directly or indirectly.

Usability: The customer can effectively discover, learn and usability the software in the easiest, most satisfying way possible. It should bring calm and cause a smile.

Sustainability: Ensuring once the software has been created it can be easily and effectively maintained into a long and unforseeable future. That includes ensuring it is cost effective, upgradable, extensible, buildable and deployable.

 

Software development is not about playing with technology.

It has nothing to do with language features, tools or frameworks.

Learning and change are not the reason for doing the work.

Cool should only apply when we find a way to improve on one of the tenents or delight a stakeholder.

Methodology, patterns, practices and paradigms are irrelevant if they don’t fit the tenents.

[videos] My first software training videos: Hoisting and Closures in JavaScript, and the MVC pattern

I recently needed to create 3 short software training videos for a software development training role I was applying for.

These are the first training videos I’ve ever created and published. I did my best to research the topics (even though I’ve worked with them for years) and try to present in the simplest way possible with examples. It’s not my finest work, but I am just getting started.

Hopefully someone finds them useful.

Any feedback is welcome at jason@jsnelders.com.

 

Hoisting in JavaScript

 

Closures in JavaScript

 

The MVC Software Pattern

Software Development: Build, to Fail. Fail, to Learn. Learn, to Succeed.

The only way to learn as a software developer is to build.

Today I started my third major application using VueJS and realised there was a better way to approach something I’ve done in the last 2 applications.

As a mature developer you must continually question and re-evaluate what you know. Keep looking for better and easier ways achieve a result, and choose to discard those that don’t suit.

I’m not ashamed to say my last 2 approaches where inadequate. It took that time, different searches, and re-framing of the problem to eventually reach the point I needed.

But coming from a Microsoft development background I’ve had a career living the philosophy: “don’t implement until version 3” (which is to say, wait until version 3 before you get it right).

In all my years I’ve never seen a developer get it “right” the first time.

Maturity is recognising success takes time and working through the process.

PHP: Recursively zip a folder/directory structure

Status: Draft (31 May 2019)

This is a work in progress. I want to record my working as I go.


What I Want

I need to zip a folder structure – ultimately, theme and plug-in folder in WordPress – using PHP.

I’m currently developing and testing on a Windows 10 PC. Ultimately it will need to work in Linux (Ubuntu), but the first step is to it working in Windows.

I started with solutions from https://gist.github.com/MarvinMenzerath/4185113/72db1670454bd707b9d761a9d5e83c54da2052ac and https://stackoverflow.com/questions/1334613/how-to-recursively-zip-a-directory-in-php but the zip file was being created, however, not files were added.

I realised the problem was the relative path for folders/files within the zip. My solution below is a modification of the referenced solutions, where I strip the source path from the fill file path of each folder and file to give the relative path to the source.

So far this works in Windows, next step is to test in Linux. I’m actively working the problem so stay tuned.

 

I created a file “D:\Temp\php\test_zip.php” with the code below.
I execute with the following command (I have XAMPP installed with includes PHP): “D:\Temp\php>D:\xampp\php\php.exe test_zip.php”.

The Code

(Aide: I used https://www.freeformatter.com/html-escape.html to convert raw PHP code to something I can past in between <pre> tags in the Classic WorPress content editor).

<?php
// Make sure the script can handle large folders/files
ini_set('max_execution_time', 600);
ini_set('memory_limit','1024M');

// Start the backup!
Zip('D:\\Temp\\php\\Source\\', './compressed.zip');
Zip('D:\\Temp\\hildas_prod_logs\\', 'D:\\Temp\\php\\backup-test.zip');
testOne('D:\\Temp\\php\\Source\\debug.log', 'D:\\Temp\\php\\compressed_testOne.zip');

echo "Finished" . "\n";


// A quick, reduced test.
// This works in Windows.
function testOne($source, $zipTo)
{
	$zip = new ZipArchive;
	if (file_exists($source) === false)
	{
		echo "Sourece does not exist" . "\n";
		return;
	}
	
	if ($zip->open($zipTo, ZIPARCHIVE::CREATE) === true) 
	{
		$zip->addFile($source, 'source\newname.txt');
		$zip->close();
		echo "OK" . "\n";
	} 
	else 
	{
		echo "FAILED" . "\n";
	}
}


// This works in Windows.
// Source and inspiration: https://gist.github.com/MarvinMenzerath/4185113/72db1670454bd707b9d761a9d5e83c54da2052ac - Marvin Menzerath. (http://menzerath.eu)
// Additional source and inspiration: https://stackoverflow.com/questions/1334613/how-to-recursively-zip-a-directory-in-php
function Zip($source, $destination)
{
    if (!extension_loaded('zip')) 
	{
		echo "Zip extension not loaded\n";
        return false;
    }
	
	if (!file_exists($source)) 
	{
		echo "Source not found:" . $source . "\n";
        return false;
    }

    $zip = new ZipArchive();
    if (!$zip->open($destination, ZIPARCHIVE::CREATE)) 
	{
		echo "Zip not created or opened\n";
        return false;
    }
	
	$raw_source = $source;

    $source = str_replace('\\', '/', realpath($source));
	
	echo "Raw source: " . $raw_source . "\n";
	echo "Clean source: " . $source . "\n";

    if (is_dir($source) === true)
    {
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
		
		$sourceWithSeparator = $source . DIRECTORY_SEPARATOR;
        foreach ($files as $file)
        {
            $file = str_replace('\\', '/', $file);

            // Ignore "." and ".." folders
            if( in_array(substr($file, strrpos($file, '/')+1), array('.', '..')) )
                continue;

            $file = realpath($file);

            if (is_dir($file) === true)
            {
				$dir_path = str_replace($sourceWithSeparator, '', $file . DIRECTORY_SEPARATOR);
				
				echo "Directory: " . $file . " (Path: " . $dir_path . ")\n";
                //$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
				
				$zip->addEmptyDir($dir_path);
            }
            else if (is_file($file) === true)
            {
				$zip_relative_path = str_replace($sourceWithSeparator, '', $file);
				
				$zip_relative_path = remove_from_start($zip_relative_path, $raw_source);
				
				echo "File: " . $file . " (Path: " . $zip_relative_path . ")\n";
                //$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
				//$zip->addFile($file, str_replace($source . '/', '', $file));
				$zip->addFile($file, $zip_relative_path);
            }
        }
    }
    else if (is_file($source) === true)
    {
        $zip->addFromString(basename($source), file_get_contents($source));
    }

    return $zip->close();
}



function remove_from_start($full_string, $prefix)
{
	if (substr($full_string, 0, strlen($prefix)) == $prefix) 
	{
		$full_string = substr($full_string, strlen($prefix));
	} 
	
	return $full_string;
}

?>

 

WordPress Shortcode: “Show If” for conditional content display

Here’s the code for a simple WordPress shortcode to conditionally display content within pages based on supplied usernames or roles.

 

Example Usage

Display to a specified user:


Display to a specified role:


Display to both a user and a role:


Display to multiple roles (comma separated list. “username” works the same):


 

Code

It’s in a GitHub gist at https://gist.github.com/vylesk/64ca3e6d3da77fb853ca7af181165e6b and below:

<?php
/**
* Plugin Name: "Show If" Shortcode
* Plugin URI: https://jsnelders.com/
* Description: Shortcode to conditionally display content if the user is in a specified role or has a specified username.
* Author: Jason Snelders
* Author URI: http://jsnelders.com
* Version: 190529.1
**/

namespace JasonSnelders\Shortcodes;

/*
*	Show the content only if the current user is one of the specified username(s) or in one ofthe role(s).
*
*	Attributes:
*		role: comma separated list of allowed roles to view the content.
*		username: comma separated list of allowed usernames to view the content.
*
*	Attrubtes combine as an OR expressess - content is displayed if they user is in the "role" list OR the "username" list.
*/
add_shortcode('show_if', 'JasonSnelders\Shortcodes\show_if_handler');

function show_if_handler($atts = [], $content = null)
{
	
	// Get supplied shortcode attributes.
	$show_if_role = "";
	$show_if_username = "";
	if(isset($atts["role"])) $show_if_role = $atts["role"];
	if(isset($atts["username"])) $show_if_username = $atts["username"];
	$show_if_role = explode(',', $show_if_role);
	$show_if_username = explode(',', $show_if_username);
	
	
	// Get the current user.
	$wp_user = \wp_get_current_user();
	$wp_user_roles = $wp_user->roles;
	$wp_user_username = $wp_user->user_login;
	
	// Check if current user can view content/
	$show_to_user = false;
	
	foreach ($wp_user_roles as $role_slug)
	{
		if ($role_slug != "" && in_array_case_insensitive($atts, $role_slug))
		{
			$show_to_user = true;
			break;
		}
	}
	
	if ($show_to_user == false)
	{
		foreach ($show_if_username as $show_username)
		{
			if ($show_username != "" && strtolower($show_username) == strtolower($wp_user_username))
			{
				$show_to_user = true;
				break;
			}
		}
	}
	
    
	ob_start();

	if ($show_to_user == true)
	{
		// Show the content
		$content = do_shortcode($content);
		echo $content;
	}
	else
	{
		// Hide the content
		echo "";
	}

	return ob_get_clean();
}


/*
*	Case-insensitive check if a value is in the array.
*	(Source: https://gist.github.com/sepehr/6351397)
*/
function in_array_case_insensitive($array, $check_value)
{
	return in_array(strtolower($check_value), array_map('strtolower', $array));
}
?>