Joshua T Kalis (he/him/his)
I build great teams and excellent software.
Refactoring
1. Very Imperative
Requirements:
Count all entries, in data, with the color 'Blue'.
var data = require("./data.json");
function countBlue () {
// Problem 1 - using variables outside it's scope
// Problem 2 - tightly coupled to accomplishing one task
var counter = 0, i = 0, len = data.length;
// performance optimized for loop
for (i; i < len; i++) {
if (data[i].Color === "blue") {
counter++;
}
}
return counter + " Color blue found.";
}
console.log(countBlue()); // Solved, no problem...
2. Imperative (but getting better)
(New) Requirements: The color to be counted is not defined yet, so make it so that the color can be passed in or changed whenever.
Uh ohs.
Requirements:
Count all entries, in a given list, with a given color.
function countColor (data, color) {
// Problem 1 - tightly coupled to counting based on a specific attribute
// Problem 2 - the value of the attribute must be exactly one value ever
var counter = 0, i = 0, len = data.length;
// performance optimized for loop
for (i; i < len; i++) {
if (data[i].Color === color) {
counter++;
}
}
return counter + " Color " + color + " found.";
}
console.log(countColor(data, "green")); // Easy, peasy.
3. Absctracted
(New) Requirements: Counting colors has gotten to be boring, lets count something else sometimes. Make it so the attribute can be passed in too.
Drat.
Requirements:
Count all entries that have a given attribute with a given value.
function countAttributeWithValue (data, attr, test) {
// Problem 1 - restricted to only one attribute being tested
// Problem 2 - restricted to only one attribute value tested
var counter = 0, i = 0, len = data.length;
// performance optimized for loop
for (i; i < len; i++) {
if (data[i][attr] === test) {
counter++;
}
}
return counter + " " + attr + " " + test + " found.";
}
console.log(countAttributeWithValue(data, "Color", "green")); // doin' good.
4. Much Better
(New) Requirement: Finer grained results are need, multiple values need to be checked per entry. Get it done quick!
Bollocks! (sorry for the profanity)
Requirements:
Count all entries that have the color 'green' and an Author containing the letter 'a'.
function condition1 (item) {
return item.Color === "green" && /a/.test(item.Author);
}
function countBasedOnTest (data, fn) {
// Problem 1 - a lot of code to counting elements in an array
// Problem 2 - still just a counter function; what about doing something
// with the entries found?
var counter = 0, i = 0, len = data.length;
// performance optimized for loop
for (i; i < len; i++) {
if (fn(data[i])) {
counter++;
}
}
return counter + " found based on passed in test function.";
}
console.log(countBasedOnTest(data, condition1)); // Under control.
4.1. More Complexity
(New) Requirements: Add another conditon to the result set; add entry with an 'Author' containing a: 'z', 'x', 'y', 'w', or 'q'.
No problem, way ahead of ya.
Requirements:
(read above)
function condition2 (item) {
return (/[zxywq]/).test(item.Author);
}
function condition_1_or_2 (item) {
return condition1(item) || condition2(item);
}
console.log(countBasedOnTest(data, condition_1_or_2));
5. Best
Reasoning:
Writing less code provides for fewer CHANCES for bugs. You only have to write the code that actually matters to the desired outcome.
console.log(data.filter(condition_1_or_2).length);
6. Go Further
Requirements:
Garbage data has infected the 'real' data, that must be filtered out before getting results; 'Hacker, Lee T' is not a valid 'Author'.
function notHacker (item) {
return item.Author !== "Hacker, Lee T.";
}
// Problem 1 - iterating over the array for each filter function
console.log(data.filter(notHacker).filter(condition_1_or_2).length);
6.1. Custom Composition
function cleanDataAndConditions (item) {
return notHacker(item) && (condition1(item) || condition2(item));
}
console.log(data.filter(cleanDataAndConditions).length);