Clean code is code that is easy to understand and easy to change.
- Clean Code
// NOT SO CLEAN
const yyyymmdd = moment().format("YYYY/MM/DD");
const m = new Date().getMonth();
let ok;
if (test.coverage > 75) {
ok = true;
}
// MUCH BETTER
const currentDate = moment().format("YYYY/MM/DD");
const currentMonth = new Date().getMonth();
const TEST_COVERAGE_THRESHOLD = 75;
const isTestCoverageThresholdMet = test.coverage > TEST_COVERAGE_THRESHOLD;
// NOT SO CLEAN
// What does this magic number mean?
setTimeout(doSomething, 86400);
// MUCH BETTER
// Declare them as capitalized named constants.
const SECONDS_PER_DAY = 60 * 60 * 24; //86400;
setTimeout(doSomething, SECONDS_PER_DAY);
// NOT SO CLEAN
const restaurant = {
restaurantName: "Best restaurant in town",
restaurantCapacity: 100,
restaurantRating: 5
};
function rateRestaurant(restaurant, rating) {
restaurant.restaurantRating = rating;
}
// MUCH BETTER
const restaurant = {
name: "Best restaurant in town",
capacity: 100,
rating: 5
};
function rateRestaurant(restaurant, rating) {
restaurant.rating = rating;
}
// NOT SO CLEAN
function createNavigationTile(title, subTitle, body, isActive) {
// ...
}
createNavigationTile("Foo", "Bar", "Baz", true);
// MUCH BETTER
function createNavigationTile({ title, subTitle, body, isActive }) {
// ...
}
createNavigationTile({
title: "Foo",
subTitle: "Bar",
body: "Baz",
isActive: true
});
// NOT SO CLEAN
function createBuilding(name) {
const buildingName = name ?? "Awesome Building Name"
// ...
}
// MUCH BETTER
function createBuilding(name = "Awesome Building Name") {
const buildingName = name;
// ...
}
// NOT SO CLEAN
const storeConfig = {
name: null,
location: "Newark",
description: "Store Description",
isActive: false
};
function createStore(config) {
config.name = config.name || "My Store";
config.location = config.location || "Unknown";
config.description = config.description || "My store is the best.";
config.isActive =
config.isActive !== undefined ? config.isActive : true;
}
createStore(storeConfig);
// MUCH BETTER
const storeConfig = {
name: "Hyvee",
//No location provided
description: "Best store.",
isActive: true
};
function createStore(config) {
let finalStoreConfig = Object.assign(
{
name: "My Store",
location: "Newark",
description: "My store is the best.",
isActive: true
},
config
);
return finalStoreConfig;
// {name: "Hyvee", location: "Newark", description: "Best store.", isActive: true}
}
createStore(storeConfig);
// NOT SO CLEAN
const address = "Terminal Way, Kansas City 64112";
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
validateCityZipCode(
address.match(cityZipCodeRegex)[1],
address.match(cityZipCodeRegex)[2]
);
// MUCH BETTER
const address = "Terminal Way, Kansas City 64112";
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
const [_, city, zipCode] = address.match(cityZipCodeRegex) ?? [];
validateCityZipCode(city, zipCode);
// NOT SO CLEAN
function notifyGroceryStores(groceryStores) {
groceryStores.forEach(groceryStore => {
const groceryStoreRecord = database.lookup(groceryStore);
if (groceryStoreRecord.isActive()) {
notify(groceryStore);
}
});
}
// MUCH BETTER
function notifyActiveGroceryStores(groceryStores) {
groceryStores.filter(isActiveGroceryStore).forEach(notify);
}
function isActiveGroceryStore(groceryStore) {
const groceryStoreRecord = database.lookup(groceryStore);
return groceryStoreRecord.isActive();
}
// NOT SO CLEAN
function createFile(name, temp) {
if (temp) {
fs.create(`./temp/${name}`);
} else {
fs.create(name);
}
}
// MUCH BETTER
function createFile(name) {
fs.create(name);
}
function createTempFile(name) {
createFile(`./temp/${name}`);
}
// NOT SO CLEAN
let animalName = "cat";
function replaceFirstLetterInAnimalName() {
animalName = animalName.replace(/^./, 'r');;
}
replaceFirstLetterInAnimalName();
console.log(animalName); // 'rat';
// MUCH BETTER
function replaceFirstLetterInAnimalName(name) {
return name.replace(/^./, 'r');
}
const animalName = "cat";
const modifiedAnimalName = replaceFirstLetterInAnimalName(animalName);
console.log(animalName); // 'cat'
console.log(modifiedAnimalName); // 'rat';
// NOT SO CLEAN
const addItemToList = (list, item) => {
list.push({ item, date: Date.now() });
};
// MUCH BETTER
const addItemToList = (list, item) => {
return [...list, { item, date: Date.now() }];
};
// NOT SO CLEAN
if (state === "loading" && isEmpty(data)) {
// ...
}
// MUCH BETTER
function shouldShowLoadingSpinner(state, data) {
return state === "loading" && isEmpty(data);
}
if (shouldShowLoadingSpinner(state, data)) {
// ...
}
// NOT SO CLEAN
function isAddressNotVerified(address) {
// ...
}
if (!isAddressNotVerified(address)) {
// ...
}
// MUCH BETTER
function isAddressVerified(address) {
// ...
}
if (isAddressVerified(address)) {
// ...
}
// NOT SO CLEAN
const email = (user && user.email) ?? "";
const street =
(user &&
user.address &&
user.address.street) ??
"";
const state =
(user &&
user.address &&
user.address.state) ??
"";
// MUCH BETTER
const email = user?.email ?? "";
const street = user?.address?.street ?? "";
const state = user?.address?.state ?? "";
// NOT SO CLEAN
if (isActive === true) {
// ...
}
if (name !== "" && name !== null && name !== undefined) {
// ...
}
const isUserEligible = user.isVerified() && user.didSubscribe() ? true : false;
// MUCH BETTER
if (isActive) {
// ...
}
if (!!name) {
// ...
}
const isUserEligible = user.isVerified() && user.didSubscribe();
// NOT SO CLEAN
function Todos() {
const { isLoading, isError, data, error } = useQuery('todos', fetchTodoList)
return (
<>
{!isLoading ? (
<ul>
{data.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
) : (
<span>Loading...</span>
)}
</>
)
}
// MUCH BETTER
function Todos() {
const { isLoading, isError, data, error } = useQuery('todos', fetchTodoList)
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return <span>Error: {error.message}</span>
}
return (
<ul>
{data.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
}
// NOT SO CLEAN
const Vehicle = function(make) {
if (!(this instanceof Vehicle)) {
throw new Error("Instantiate Vehicle with `new`");
}
this.make = make;
};
Vehicle.prototype.move = function move() {};
const Car = function(make, color) {
if (!(this instanceof Car)) {
throw new Error("Instantiate Car with `new`");
}
Vehicle.call(this, make);
this.color = color;
};
Car.prototype = Object.create(Vehicle.prototype);
Car.prototype.constructor = Car;
Car.prototype.getColor = function getColor() {};
// MUCH BETTER
class Vehicle {
constructor(make) {
this.make = make;
}
move() {
/* ... */
}
}
class Car extends Vehicle {
constructor(make, color) {
super(make);
this.color = color;
}
getColor() {
/* ... */
}
}
// NOT SO CLEAN
getStore(function (err, store) {
getTransactions(store, function (err, transactions) {
getReports(transactions, function (err, reports) {
sendReports(reports, function (err) {
console.error(err);
});
});
});
});
// MUCH BETTER
getStore()
.then(getTransactions)
.then(getReports)
.then(sendReports)
.catch((err) => console.error(err));
// EVEN BETTER
async function sendReportsToStoreManagement() {
try {
const store = await getStore();
const transactions = await getTransactions(store);
const reports = await getReports(transactions);
return sendReports(reports);
} catch (err) {
console.error(err);
}
}
// NOT SO CLEAN
try {
functionThatMightThrowError();
} catch (error) {
console.log(error);
}
// MUCH BETTER
try {
functionThatMightThrowError();
} catch (error) {
// Better than console.log:
console.error(error);
// Another option:
notifyUserOfError(error);
// Another option:
reportErrorToService(error);
// OR do all three!
}
// NOT SO CLEAN
getdata()
.then(data => {
functionThatMightThrowError(data);
})
.catch(error => {
console.log(error);
});
// MUCH BETTER
getdata()
.then(data => {
functionThatMightThrowError(data);
})
.catch(error => {
// Better than console.log:
console.error(error);
// Another option:
notifyUserOfError(error);
// Another option:
reportErrorToService(error);
// OR do all three!
});
// NOT SO CLEAN
const MIN_TEMPERATURE = 32;
const maxTemperature = 120;
const fruits = ["Apple", "Banana", "Kiwi"];
const Vegetables = ["Potato", "Cabbage", "Onion"];
function resetData() {}
function refetch_data() {}
class vehicle {}
class Car {}
// MUCH BETTER
const MIN_TEMPERATURE = 32;
const MAX_TEMPARATURE = 120;
const fruits = ["Apple", "Banana", "Kiwi"];
const vegetables = ["Potato", "Cabbage", "Onion"];
function resetData() {}
function refetchData() {}
class Vehicle {}
class Car {}
// NOT SO CLEAN
function generateHash(data) {
// The hash
let hash = 0;
// Length of string
const length = data.length;
// Loop through every character in data
for (let i = 0; i < length; i++) {
// Get character code.
const char = data.charCodeAt(i);
// Make the hash
hash = (hash << 5) - hash + char;
// Convert to 32-bit integer
hash &= hash;
}
}
// MUCH BETTER
function generateHash(data) {
let hash = 0;
const length = data.length;
for (let i = 0; i < length; i++) {
const char = data.charCodeAt(i);
hash = (hash << 5) - hash + char;
// Convert to 32-bit integer
hash &= hash;
}
}
// NOT SO CLEAN
/**
* 2022-01-01: Initial Commit (AF)
* 2022-01-02: Added new feature (JD)
* 2022-01-03: Fixed bug (AF)
* 2022-01-05: Added more functionality (JD)
*/
function computeAverage(numbers = []) {
// let sum = 0;
// for (let i = 0; i < numbers.length; i++) {
// sum += numbers[i];
// }
const sum = addNumbers(numbers);
return sum / numbers.length;
}
// MUCH BETTER
function computeAverage(numbers = []) {
return addNumbers(numbers) / numbers.length;
}
// MUCH BETTER
/**
* Returns if input is a prime number or not.
*
* @param {number} number - The number to be checked.
* @return {bool} whether the number is a prime number.
*/
function isPrime(number) {
// ...
}
// NOT SO CLEAN
describe("user info form", () => {
it('validates form workflows', () => {
const {handleSubmit, user} = setupSuccessCase()
expect(handleSubmit).toHaveBeenCalledTimes(1)
expect(handleSubmit).toHaveBeenCalledWith(user)
const {handleSubmit, errorMessage} = setupWithNoUsername()
expect(errorMessage).toHaveTextContent(/username is required/i)
expect(handleSubmit).not.toHaveBeenCalled()
const {handleSubmit, errorMessage} = setupWithNoPassword()
expect(errorMessage).toHaveTextContent(/password is required/i)
expect(handleSubmit).not.toHaveBeenCalled()
})
});
// MUCH BETTER
describe("user info form", () => {
it('calls onSubmit with the username and password', () => {
const {handleSubmit, user} = setupSuccessCase()
expect(handleSubmit).toHaveBeenCalledTimes(1)
expect(handleSubmit).toHaveBeenCalledWith(user)
})
it('shows an error message when submit is clicked and no username is provided', () => {
const {handleSubmit, errorMessage} = setupWithNoUsername()
expect(errorMessage).toHaveTextContent(/username is required/i)
expect(handleSubmit).not.toHaveBeenCalled()
})
it('shows an error message when password is not provided', () => {
const {handleSubmit, errorMessage} = setupWithNoPassword()
expect(errorMessage).toHaveTextContent(/password is required/i)
expect(handleSubmit).not.toHaveBeenCalled()
})
});
// NOT SO CLEAN
function combine(firstInput, secondInput) {
if (
(typeof firstInput === "number" && typeof secondInput === "number") ||
(typeof firstInput === "string" && typeof secondInput === "string")
) {
return firstInput + secondInput;
}
throw new Error("Must be of type String or Number");
}
There are only two hard things in Computer Science: cache invalidation and naming things.
- Phil Karlton