27/09/2020
Introduction
This is just a quick post about a few of the problems I faced when I was making a password generator for my own records. You probably won’t find it helpful unless you’re making a password generator too.
The First Array
First things first, we’re going to need an array of letters for our password generator to select from. Let’s type that out:
const alphabet = ['a','b','c','d','e','f']
...You gotta be kidding me. We’re about to die from boredom. We’ve typed 25 characters just to get 6 letters in our array. There’s got to be a better way than this. A quick Google search takes us to StackOverflow.com with this solution:
alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
Let’s do console.log(alphabet)
to see if it works:
Array(26) [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", … ]
Good stuff!
Debugging
Sometimes the generated password does not match the password length that the user entered. Here is a screenshot where the user asked for a password 6 characters long but the password generator only created one that was 3 characters long.
Why would it do that? How could our precious code that we gave life to, betray us and stab us in the back like that???
I wish I could say I was a genius that was able to find this bug instantly but I’m not. I did manage to narrow it down and discovered it was only happening when the user selected the “Include special characters” checkbox.
So out of desperation I started removing characters one by one from the special characters array, saving it, and generating a few passwords to see if it had magically fixed itself. And at one point it was magically fixed. Then it hit me. The ‘<’ and ‘>’ characters.
output.innerHTML = hereIsYourPassword;
The password is displayed in a div
called output
using inner.HTML
. This meant that if the password included those special characters, part of the password was being turned into HTML tags which would not be displayed in the output
. Rookie mistake.
Refactoring 100 Million Else If Statements
The password generator ended up with 4 checkboxes. One for lower case letters, one for upper case letters, one for numbers and one for special characters. This resulted in approximately 100 million else if statements
to cover every combination of checkbox that could be checked. Shown below:
function chooseFunction() {
if (
includeLowerCase.checked === false &&
includeSymbols.checked === false &&
includeNumbers.checked === false &&
includeUpperCase.checked === false
) {
checkPasswordInput();
} else if (
includeLowerCase.checked === true &&
includeSymbols.checked === false &&
includeNumbers.checked === false &&
includeUpperCase.checked === false
) {
checkPasswordInput();
generateBasicPassword();
} else if (
includeLowerCase.checked === true &&
includeSymbols.checked === true &&
includeNumbers.checked === false &&
includeUpperCase.checked === false
) {
checkPasswordInput();
generateBasicPasswordWithSpecialSymbols();
} else if (
includeLowerCase.checked === true &&
includeSymbols.checked === false &&
includeNumbers.checked === true &&
includeUpperCase.checked === false
) {
checkPasswordInput();
generateBasicPasswordWithNumbers();
} else if (
includeLowerCase.checked === true &&
includeSymbols.checked === false &&
includeNumbers.checked === false &&
includeUpperCase.checked === true
) {
checkPasswordInput();
generateBasicPasswordWithUpperCase();
} else if (
includeLowerCase.checked === true &&
includeSymbols.checked === true &&
includeNumbers.checked === true &&
includeUpperCase.checked === false
) {
checkPasswordInput();
generateBasicPasswordWithSpecialSymbolsAndNumbers();
} else if (
includeLowerCase.checked === true &&
includeSymbols.checked === true &&
includeNumbers.checked === false &&
includeUpperCase.checked === true
) {
checkPasswordInput();
generateBasicPasswordWithSpecialSymbolsAndUpperCase();
} else if (
includeLowerCase.checked === true &&
includeSymbols.checked === false &&
includeNumbers.checked === true &&
includeUpperCase.checked === true
) {
checkPasswordInput();
generateBasicPasswordWithNumbersAndUpperCase();
} else if (
includeLowerCase.checked === true &&
includeSymbols.checked === true &&
includeNumbers.checked === true &&
includeUpperCase.checked === true
) {
checkPasswordInput();
generateBasicPasswordWithAllOptions();
} else if (
includeLowerCase.checked === false &&
includeSymbols.checked === true &&
includeNumbers.checked === false &&
includeUpperCase.checked === false
) {
checkPasswordInput();
generateSpecialCharactersOnly();
} else if (
includeLowerCase.checked === false &&
includeSymbols.checked === false &&
includeNumbers.checked === true &&
includeUpperCase.checked === false
) {
checkPasswordInput();
generateNumbersOnly();
} else if (
includeLowerCase.checked === false &&
includeSymbols.checked === false &&
includeNumbers.checked === false &&
includeUpperCase.checked === true
) {
checkPasswordInput();
generateUpperCaseOnly();
} else if (
includeLowerCase.checked === false &&
includeSymbols.checked === true &&
includeNumbers.checked === true &&
includeUpperCase.checked === false
) {
checkPasswordInput();
generateSpecialSymbolsWithNumbers();
} else if (
includeLowerCase.checked === false &&
includeSymbols.checked === true &&
includeNumbers.checked === false &&
includeUpperCase.checked === true
) {
checkPasswordInput();
generateSpecialSymbolsWithUpperCase();
} else if (
includeLowerCase.checked === false &&
includeSymbols.checked === true &&
includeNumbers.checked === true &&
includeUpperCase.checked === true
) {
checkPasswordInput();
generateSymbolsPasswordWithNumbersAndUpperCase();
} else if (
includeLowerCase.checked === false &&
includeSymbols.checked === false &&
includeNumbers.checked === true &&
includeUpperCase.checked === true
) {
checkPasswordInput();
generateNumbersPasswordWithUpperCase();
}
}
The aspiring developer inside me was smart enough to realise “Hey! I don’t think this counts as good code man. Maybe you should ask someone that actually knows what they’re doing for help?”
So I asked for help on DThompsonDev’s Discord channel called Commit Your Code. The reply was to use 4 if statements
and concatenate the arrays as needed. This changed the 100 million else if statements
above to this:
function generateAllPasswords() {
let finalArray = [];
if (includeLowerCase.checked === true) {
finalArray = finalArray.concat(alphabetLowerCase);
}
if (includeSymbols.checked === true) {
finalArray = finalArray.concat(specialCharacters);
}
if (includeNumbers.checked === true) {
finalArray = finalArray.concat(numbers);
}
if (includeUpperCase.checked === true) {
finalArray = finalArray.concat(alphabetUpperCase);
}
checkPasswordInput();
getCharacters(finalArray);
}
I’ve never seen multiple if statements
used in such a way one after the other. I've only ever seen 1 if statement
or many else if statements
. This refactoring also meant I could remove all the separate functions I had declared for each combination of checkbox and reduced it to a single function. The overall result was going from 605 lines of JavaScript down to 158.
Conclusion
Make sure you ask for help when needed. Going through every combination of checkbox took me ages. Then another person looked at the code for a few minutes and said “Try it this way.”
Well that’s about all of the problems I can remember since it’s been a couple of weeks since I made the password generator. Bye-bye.
Top comments (1)
GENERA's 35 years of experience feriados en chilein the industry speaks to its deep understanding of the challenges faced by businesses when it comes to managing their workforce effectively.