The elegance of optimised syntax

The following is an article I wrote on Medium back in September 2014. I just discovered it again and liked it so I thought I'd 'reprint' it here.


While staring at some code recently (code that wasn’t working) I was struck by how my code has improved over time by simple changes of syntax. As an example I’ll use toggling the value of a boolean variable: myvar

For those that don’t know a boolean value can only be either true or false. Some languages also permit the use of 1 or 0.

So when I first started out I would have explicitly compared the value to true in an if statement. If the variable is true, set it to false. Otherwise, set it to true:

if(myvar === true){  
   myvar = false;
} else {
   myvar = true;
}

After learning that anything other than a ‘falsey’ value always equates to true I omitted the explicit comparison:

if(myvar){  
   myvar = false;
} else {
   myvar = true;
}

An embarrassingly long time went by before I discovered the ternary operator making simple conditional assigns very concise:

myvar = (myvar) ? false : true;  

I thought this was as elegant as it could get. A single line, a single declaration of the variable to be assigned and the two options separated by simple punctuation.

However, the application of simple logic and the use of the not operator (!) can make the original five line, forty-seven character if statement in to a single line, thirteen character piece of poetry:

myvar = !myvar;  

In case this doesn’t make sense to you, it sets the variable to whatever it is not. So if myvar is true it becomes not true, or false. If false it becomes not false, or true.

Each code block above does exactly the same thing and probably has similar performance impact. Yet the effect it has on code readability and source code file size are surely significant.

Flexbox space-between and the last row

I'm smitten with flexbox. To really get to grips with it I built a comprehensive, minimum styling site to really grasp how to do layout with it.

I created a 'card' layout with eight cards and had two rows of four. Looked great:

Two rows of four cards

So I tested the responsiveness and at my desired breakpoint the rows change to three cards (thanks to flex-wrap) and I was struck something that didn't look good:

Eight cards across three rows

Despite a lot of playing around with flexbox properties and margins etc. I could not find a pure css solution so I had to embrace some 'progressive enhancement' and turn to JavaScript.

It struck me that in order to shift the last element along I would need an invisible element. Since I couldn't be certain of how many cards there would be, I'd need to add enough invisible elements to bring the total up to a number divisible by both three and four. The smallest number that divides by both is twelve.

The first function called takes an ID of the element that contains the cards. It then counts the child elements and passes that to the checkCount() function:

var container = document.getElementById(container_id);  
var card_count = container.children.length;  
checkCount(card_count, ...  

The checkCount() function takes the total number of cards and a callback function as arguments. By using the modulus operator (%) we can test to see if any remainder exists after dividing by twelve. Since a remainder other than zero is treated as true we know when we hit the right number when the if statement is false.

So if we do get a remainder, we increment the count and pass that to the same function. Hurrah for recursion!

function checkCount(current_total, next){  
  if(current_total % 12){ // 12 is smallest number that 3 and 4 go in to
    current_total += 1; // Proper way to do ++
    checkCount(current_total, next); // Recursion!
  } else {
    next(current_total);
  }
}

With the final count returned we can find the number of extra elements required by subtracting the original card count from it. Using this in a for loop we create elements with the class dummy_card and append them to the original container.

var dummy_element;  
for(i=0; i<(final_count-card_count); i++){  
  dummy_element = document.createElement('div');
  dummy_element.className = 'dummy_card';
  container.appendChild(dummy_element);
}

By giving the dummy_card a height of zero in the CSS it won't affect the look of the page. Although this approach does pollute the DOM a bit, by using empty div elements we don't affect the semantics. Seems to work.

Eight cards across three rows, fixed

Here's the full code:

function checkCount(current_total, next){  
  if(current_total % 12){ // 12 is smallest number that 3 and 4 go in to
    current_total += 1; // Proper way to do ++
    checkCount(current_total, next); // Recursion!
  } else {
    next(current_total);
  }
}
function addDummyElementsToCards(container_id){  
  var container = document.getElementById(container_id);
  var card_count = container.children.length;
  checkCount(card_count, function(final_count){
    var dummy_element;
    for(i=0; i<(final_count-card_count); i++){
      dummy_element = document.createElement('div');
      dummy_element.className = 'dummy_card';
      container.appendChild(dummy_element);
    }
  });
}
addDummyElementsToCards('cards');  

Internet Explorer EOL

I no longer support any version of Internet Explorer prior to version 11. Microsoft has, as of today, ended their support for them. This means that no bug-fixes, compatibility fixes, and more important security updates will be forthcoming.

There is no longer any compelling reason to use one of these old browsers. Security alone should justify moving to IE11, Edge, or one of the other free browsers.

I pulled up the analytics of the sites I have access to. And after a quick bit of tabulation and some maths I can say that on average 3% of visitors to the sorts of sites I build use IE with a version number less than 11.

Who knows what proportion of that 3% actually convert to completing some goal. Frankly, it's not worth the effort supporting them.

Diffie-Hellman for TLS

After successfully enabling Let's Encrypt for my domain, I ran the test over at SSL Labs and was disappointed to see I only scored a C grade.

It seems that because my Nginx configuration supported SSLv3 it was susceptible to the POODLE attack. And thus regardless of anything else the grade was capped at C. This was easily fixed however by adding the following line to nginx.conf:

http {  
    ...
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ...
}

I ran the test again but this time only scored a B grade. Here's why:

Warning! This site uses a commonly-shared 1024-bit Diffie-Hellman group, and might be in range of being broken by a nation-state. It might be a good idea to generate a unique, 2048-bit group for the site.

Luckily, the kind folks over at weakdh.org provide a Guide to Deploying Diffie-Hellman for TLS. To summarise, do the following:

First thing to do is generate a dhparams.pem. I put it in my /etc/nginx/sites-available directory, but it doesn't really matter where you put it as long as it's a fairly safe location:

openssl dhparam -out /etc/nginx/sites-available/dhparams.pem 2048  

Now in the server block for your domain (by default this is in /etc/nginx/sites-available/default) add the following lines:

server {  
    ...
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/nginx/sites-available/dhparams.pem;
    ...

Now reload Nginx:

sudo nginx -s reload  

These simple steps have garnered me an A grade.

A grade on SSL Labs

Implementing Let's Encrypt

Updated Now that Let's Encrypt is in public beta I've updated this to suit.

These are exciting times for the web. Secure connections have been around for a long time and are now expected and trusted by the public. Unfortunately they're also very expensive, usually around $99 per year.

But huzzah and hooray, we now have Let's Encrypt, a service from the EFF, Mozilla, Cisco and others to provide FREE TLS encryption for any website. You can read more about the mission here: https://letsencrypt.org/about/

At the moment the service is in public beta which means they're still ironing out the bugs, but it's currently serving tens of thousands of certs and seems to be holding up fine.

For the purposes of this little walk-through I'm using Ubuntu 14.10 and Nginx.

One of the goals of Let's Encrypt is that it be automatic. In time this will include configuring the server too (be that Apache, Nginx, or another) and it already does a pretty good job but there's definitely more work to do.

I'm going to show how get just the cert files and configure Nginx manually. So to start with clone the Let's Encrypt software somewhere, I put it in my home directory:

git clone https://github.com/letsencrypt/letsencrypt  

Ideally before the next step make sure you stop any service using port 80. There is a 'webroot' option to circumvent this and you can read more on the How it works page. But in my case I'm happy killing Nginx for a couple of minutes:

sudo service nginx stop  

Now cd in to the new directory and run the software with the following parameters:

cd letsencrypt  
./letsencrypt-auto certonly

The first time you run the program it will ask for an email address and ask that you agree with the T's and C's.

Lets Encrypt email address screen

Lets Encrypt terms and conditions screen

Finally it will ask for your domain(s). Separate these either with a space or a comma.

That's it! If all goes well the necessary files will be created here: /etc/letsencrypt/live/<yourdomain>/

To add to Nginx, add or change your sites-available file to look like this:

server {  
    listen 443 ssl;
    server_name lewiswalsh.com;
    ssl_certificate     /etc/letsencrypt/live/lewiswalsh.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/lewiswalsh.com/privkey.pem;

Next I created a server block to redirect https://www.lewiswalsh.com to https://lewiswalsh.com and one to redirect the insecure versions of those domains:

server {  
    listen       443 ssl;
    server_name  www.lewiswalsh.com;
    return       301 https://lewiswalsh.com$request_uri;
}
server {  
    listen       80;
    server_name  lewiswalsh.com www.lewiswalsh.com;
    return       301 https://lewiswalsh.com$request_uri;
}

Restart Nginx and all should be well.

sudo service nginx restart  

Since Let's Encrypt certificates expire every ninety days you'll need to manually renew. Eventually this can be automated, but for now just run the following command again when your certs expire:

./letsencrypt-auto certonly

While you're at it, you may as well beef up the Diffie-Hellman cyphers to get that A-grade SSL.