SlideShare a Scribd company logo
Clean codeClean codeAdapted in JavaScript
Clean code in JavaScript
AgendaAgenda
Variables
Functions
Classes
Miscellaneous
VariablesVariables
There are only two hard things inThere are only two hard things in
Computer Science: cache invalidationComputer Science: cache invalidation
and naming things.and naming things.
There are only two hard things inThere are only two hard things in
Computer Science: cache invalidationComputer Science: cache invalidation
and naming things.and naming things.
“ Phil Karlton
Use meaningful and pronounceable variable namesUse meaningful and pronounceable variable names
const yyyymmdstr = moment().format('YYYY/MM/DD');
const yearMonthDay = moment().format('YYYY/MM/DD');
Use the same vocabulary for the same type of variableUse the same vocabulary for the same type of variable
getUserInfo();
getClientData();
getCustomerRecord();
getUser();
Use searchable namesUse searchable names
// What the heck is 525600 for?
for (let i = 0; i < 525600; i++) {
runCronJob();
}
// Declare them as capitalized `const` globals.
const MINUTES_IN_A_YEAR = 525600;
for (let i = 0; i < MINUTES_IN_A_YEAR; i++) {
runCronJob();
}
Keep convention in mindKeep convention in mind
class AnimalSoSweet {} // UpperCamelCase
let anAnimal = new AnimalSoSweet(); // LowerCamlCase
function sendARequest(requestToSend){};// LowerCamlCase
const NB_MS_IN_HOUR = 3600; // SCREAMING_SNAKE_CASE
Use explanatory variablesUse explanatory variables
const cityStateRegex = /^(.+)[,s]+(.+?)s*(d{5})?$/;
saveCityState(
cityStateRegex.match(cityStateRegex)[1],
cityStateRegex.match(cityStateRegex)[2]
);
const cityStateRegex = /^(.+)[,s]+(.+?)s*(d{5})?$/;
const match = cityStateRegex.match(cityStateRegex)
const city = match[1];
const state = match[2];
saveCityState(city, state);
Avoid Mental MappingAvoid Mental Mapping
const locations = ['Austin', 'New York', 'San Francisco'];
locations.forEach((l) => {
doStuff();
doSomeOtherStuff();
// ...
// ...
// ...
// Wait, what is `l` for again?
dispatch(l);
});
const locations = ['Austin', 'New York', 'San Francisco'];
locations.forEach((location) => {
doStuff();
doSomeOtherStuff();
// ...
// ...
// ...
dispatch(location);
});
Don't add unneeded contextDon't add unneeded context
const Car = {
carMake: 'Honda',
carModel: 'Accord',
carColor: 'Blue'
};
function paintCar(car) {
car.carColor = 'Red';
}
const Car = {
make: 'Honda',
model: 'Accord',
color: 'Blue'
};
function paintCar(car) {
car.color = 'Red';
}
Short-circuiting is cleaner than conditionalsShort-circuiting is cleaner than conditionals
function createMicrobrewery(name) {
let breweryName;
if (name) {
breweryName = name;
} else {
breweryName = 'Hipster Brew Co.';
}
}
function createMicrobrewery(name) {
const breweryName = name || 'Hipster Brew Co.'
}
FunctionsFunctions
Function arguments (2 or fewer ideally)Function arguments (2 or fewer ideally)
function createMenu(title, body, buttonText, cancellable) {
// ...
}
const menuConfig = {
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
}
function createMenu(menuConfig) {
// ...
}
Functions should do one thing (Small !)Functions should do one thing (Small !)
function emailClients(clients) {
clients.forEach(client => {
const clientRecord = database.lookup(client);
if (clientRecord.isActive()) {
email(client);
}
});
}
function emailClients(clients) {
clients
.filter(isClientActive)
.forEach(email);
}
function isClientActive(client) {
const clientRecord = database.lookup(client);
return clientRecord.isActive();
}
Don't use flags as function parametersDon't use flags as function parameters
function createFile(name, temp) {
if (temp) {
fs.create('./temp/' + name);
} else {
fs.create(name);
}
}
function createFile(name) {
fs.create(name);
}
function createTempFile(name) {
createFile('./temp/' + name);
}
Function names should say what they doFunction names should say what they do
function dateAdd(date, month) {
// ...
}
const date = new Date();
/* It's hard to to tell from the
function name what is added
*/
dateAdd(date, 1);
function dateAddMonth(date, month) {
// ...
}
const date = new Date();
dateAddMonth(date, 1);
Function should not have side effectFunction should not have side effect
let name = 'Ryan McDermott';
function splitIntoFirstAndLastName() {
name = name.split(' ');
}
splitIntoFirstAndLastName();
function splitIntoFirstAndLastName(name) {
return name.split(' ');
}
const name = 'Ryan McDermott'
const newName = splitIntoFirstAndLastName(name);
Use default arguments instead of short circuitingUse default arguments instead of short circuiting
function writeForumComment(subject, body) {
subject = subject || 'No Subject';
body = body || 'No text';
}
function writeForumComment(
subject = 'No subject',
body = 'No text') {
// ...
}
Encapsulate conditionalsEncapsulate conditionals
if (fsm.state === 'fetching' && isEmpty(listNode)) {
// ...
}
function shouldShowSpinner(fsm, listNode) {
return fsm.state === 'fetching' && isEmpty(listNode);
}
if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
// ...
}
Sort correctly callers and calleeSort correctly callers and callee
function doVerySpecificThing(){
//...
}
function doSpecificThing(){
//...
doVerySpecificThing();
}
function doThing(){
//...
doSpecificThing();
}
function doThing(){
//...
doSpecificThing();
}
function doSpecificThing(){
//...
doVerySpecificThing();
}
function doVerySpecificThing(){
//...
}
Prefer functional programming over imperativePrefer functional programming over imperative
const programmerOutput = [
{ name: 'Uncle Bobby', linesOfCode: 500 },
{ name: 'Suzie Q', linesOfCode: 1500 }
//....
];
let totalOutput = 0;
for (let i = 0; i < programmerOutput.length; i++) {
totalOutput += programmerOutput[i].linesOfCode;
}
const programmerOutput = [
{ name: 'Uncle Bobby', linesOfCode: 500 },
{ name: 'Suzie Q', linesOfCode: 1500 }
//....
];
const totalOutput = programmerOutput
.map((programmer) => programmer.linesOfCode)
.reduce((acc, linesOfCode) => acc + linesOfCode, 0);
Prefer polymorphism over lot of conditionalsPrefer polymorphism over lot of conditionals
class Airplane {
// ...
getCruisingAltitude() {
switch (this.type) {
case '777':
return this.getMaxAltitude() - this.getPassengerCount();
case 'Air Force One':
return this.getMaxAltitude();
case 'Cessna':
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
}
class Airplane {}
class Boeing777 extends Airplane {
getCruisingAltitude() {
return this.getMaxAltitude() - this.getPassengerCount();
}
}
class AirForceOne extends Airplane {
getCruisingAltitude() {
return this.getMaxAltitude();
}
}
Never everNever ever lets dead or commented code !!!lets dead or commented code !!!
// function oldRequestModule(url) {
// ...
// }
function newRequestModule(url) {
// ...
}
const req = newRequestModule;
inventoryTracker('apples', req, 'www.inventory-awesome.io');
function newRequestModule(url) {
// ...
}
const req = newRequestModule;
inventoryTracker('apples', req, 'www.inventory-awesome.io');
ClassesClasses
SSingle responsibilityingle responsibility
OOpen-closedpen-closed
LLiskov substitutioniskov substitution
IInterface segregationnterface segregation
DDependency injectionependency injection
SOLIDSOLID principlesprinciples
en.wikipedia.org/wiki/SOLID_(object-oriented_design)
Single Responsibility Principle (Single Responsibility Principle (SSRP)RP)
class UserService {
saveUser(user){
eventEmmitter.dispatch(ADD_USER, user);
return db.exec('INSERT VALUES ...', user);
}
}
class UserResource {
//...
save(user){
return db.exec('INSERT VALUES ...', user);
}
}
class UserService {
//...
saveUser(user){
eventEmmitter.dispatch(ADD_USER, user);
return userRessource.save(user)
}
}
"There should never be more than one reason for a class to change"
Open/Closed Principle (Open/Closed Principle (OOCP)CP)
class ExpenseController {
constructor() {}
addNewExpense(expense) {
if (this.validateExpense(expense)){
expenseService.save(expense);
}
}
validateExpense (expense){
return !!expense.description;
}
}
class UserAuth {
constructor(user) {
this.user = user;
}
verifyCredentials() {
// ...
}
}
class ExpenseController {
constructor(validators) {this.validators=validators;}
addNewExpense(expense) {
if (this.validateExpense(expense)){
expenseService.save(expense);
}
}
validateExpense (expense){
return this.validators.every(validator => {
return validator.isValid(expense));
});
}
}
"open for extension, but closed for modification"
Liskov substitution principle (Liskov substitution principle (LLSP)SP)
class Rectangle {
//...
setWidth(width) {
this.width = width;
}
setHeight(height) {
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
class Square extends Rectangle {
// ...
setWidth(width) {
this.width = width;
this.height = width;
}
setHeight(height) {
this.width = height;
this.height = height;
}
}
function renderLargeRectangles(rectangles) {
rectangles.forEach((rectangle) => {
rectangle.setWidth(4);
rectangle.setHeight(5);
const area = rectangle.getArea();//Will return 25 for Square. Should be 20.
rectangle.render(area);
});
}
const rectangles = [new Rectangle(), new Rectangle(), new Square()];
renderLargeRectangles(rectangles);
Liskov substitution principle (Liskov substitution principle (LLSP)SP)
class Shape {
setColor(color) {
// ...
}
render(area) {
// ...
}
}
class Rectangle extends Shape {
constructor() {
super();
this.width = 0;
this.height = 0;
}
setWidth(width) {
this.width = width;
}
setHeight(height) {
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
class Square extends Shape {
constructor() {
super();
this.length = 0;
}
setLength(length) {
this.length = length;
}
getArea() {
return this.length * this.length;
}
}
function renderLargeShapes(shapes) {
shapes.forEach((shape) => {
switch (shape.constructor.name) {
case 'Square':
shape.setLength(5);
break;
case 'Rectangle':
shape.setWidth(4);
shape.setHeight(5);
}
const area = shape.getArea();
shape.render(area);
});
}
Interface segregation principle (Interface segregation principle (IISP)SP)
class ACar {
run(){
throw new Error('SubType of car should implement run');
}
fillFuel(){
throw new Error('SubType of car should implement fillFuel');
}
}
class MyOldCar extends ACar{
run(){
// run ...
}
fillFuel(){
// handle fillFuel
}
}
class MyElectricCar extends ACar{
run(){
// run ...
}
fillFuel(){
// Not necessary
}
}
"Clients should not be forced to depend upon interfaces that they do not use."
Interface segregation principle (Interface segregation principle (IISP)SP)
class ACar {
run(){
throw new Error('SubType of car should implement run');
}
}
const FuelCar = (Superclass) => class extends Superclass {
fillFuel() {
throw new Error('SubType of FuelCar should implement fillFuel');
}
}
class MyOldCar extends FuelCar(ACar){
run(){
// run ...
}
fillFuel(){
// handle fillFuel
}
}
const ElectricCar = (Superclass) => class extends Superclass {
reload() {
throw new Error('SubType of ElectricCar should implement reload');
}
}
class MyElectricCar extends ElectricCar(ACar){
run(){
// run ...
}
reload(){
// handle reload
}
}
"Clients should not be forced to depend upon interfaces that they do not use."
Dependency Inversion Principle (Dependency Inversion Principle (DDIP)IP)
"1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
2. Abstractions should not depend upon details. Details should depend on abstractions."
class UserController {
constructor(){
this.userService = new UserService();
}
save(user){
this.userService.save(user);
}
}
class UserController {
constructor(userService){
this.userService = userService;
}
save(user){
this.userService.save(user);
}
}
Use method chainingUse method chaining
"1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
2. Abstractions should not depend upon details. Details should depend on abstractions."
class User {
constructor(name, age){
this.name = name;
this.age = age;
}
setName(name){
this.name = name;
}
setAge(age){
this.age = age;
}
}
const user = new User();
user.setName('Mathieu');
user.setAge('28');
class User {
constructor(name, age){
this.name = name;
this.age = age;
}
setName(name){
this.name = name;
return this;
}
setAge(age){
this.age = age;
return this;
}
}
const user = new User()
.setName('Mathieu')
.setAge('28');
MiscellaneousMiscellaneous   
Only comment things that have business logic complexity.Only comment things that have business logic complexity.
function hashIt(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;
}
}
"Comments are an apology, not a requirement. Good code mostly documents itself."
function hashIt(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;
}
}
Bad commentsBad comments
/**
* 2016-12-20: Removed monads, didn't understand them (RM)
* 2016-10-01: Improved using special monads (JP)
* 2016-02-03: Removed type-checking (LI)
* 2015-03-14: Added combine with type-checking (JR)
*/
////////////////////////////////////////////////////////////////////////////////
// Scope Model Instantiation
////////////////////////////////////////////////////////////////////////////////
$scope.model = {
menu: 'foo',
nav: 'bar'
};
while (toto < MAX_VALUES){
if (test > MIN_VALUES){
} // if
} // while
FollowFollow
the cleanthe clean
code rulescode rules
slides.com/mbreton/clean-code-javascriptslides.com/mbreton/clean-code-javascript
github.com/ryanmcdermott/clean-code-javascriptgithub.com/ryanmcdermott/clean-code-javascript
Ad

Recommended

Javascript Clean Code
Javascript Clean Code
Petra Barus
 
Mobile application development ppt
Mobile application development ppt
tirupathinews
 
Introduction to React Native
Introduction to React Native
Sambhu Lakshmanan
 
Diabetes Mellitus
Diabetes Mellitus
MD Abdul Haleem
 
Power Point Presentation on Artificial Intelligence
Power Point Presentation on Artificial Intelligence
Anushka Ghosh
 
Republic Act No. 11313 Safe Spaces Act (Bawal Bastos Law).pptx
Republic Act No. 11313 Safe Spaces Act (Bawal Bastos Law).pptx
maricelabaya1
 
Hypertension
Hypertension
Ratheeshkrishnakripa
 
Nursing process
Nursing process
Dr. Binu Babu Nursing Lectures Incredibly Easy
 
Clean code
Clean code
Arturo Herrero
 
Junit
Junit
FAROOK Samath
 
Clean Code JavaScript
Clean Code JavaScript
Riza Fahmi
 
Kotlin presentation
Kotlin presentation
MobileAcademy
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
Johnny Sung
 
Introduction to VueJS & Vuex
Introduction to VueJS & Vuex
Bernd Alter
 
JUnit 5 - The Next Generation
JUnit 5 - The Next Generation
Kostadin Golev
 
Clean code
Clean code
ifnu bima
 
Clean Code Principles
Clean Code Principles
YeurDreamin'
 
Clean Code
Clean Code
Dmytro Turskyi
 
Introduction to kotlin and OOP in Kotlin
Introduction to kotlin and OOP in Kotlin
vriddhigupta
 
Swift Programming Language
Swift Programming Language
Giuseppe Arici
 
JUNit Presentation
JUNit Presentation
Animesh Kumar
 
Angular Advanced Routing
Angular Advanced Routing
Laurent Duveau
 
大家來學GObject
大家來學GObject
Shu-Yu Fu
 
React and redux
React and redux
Mystic Coders, LLC
 
Angular routing
Angular routing
Sultan Ahmed
 
Angular Unit Testing
Angular Unit Testing
Alessandro Giorgetti
 
Spring boot Introduction
Spring boot Introduction
Jeevesh Pandey
 
OOP with Java - Continued
OOP with Java - Continued
Hitesh-Java
 
Good Coding Practices with JavaScript
Good Coding Practices with JavaScript
🏁 Pierre-Henry Soria 💡
 
OOP Best Practices in JavaScript
OOP Best Practices in JavaScript
Haim Michael
 

More Related Content

What's hot (20)

Clean code
Clean code
Arturo Herrero
 
Junit
Junit
FAROOK Samath
 
Clean Code JavaScript
Clean Code JavaScript
Riza Fahmi
 
Kotlin presentation
Kotlin presentation
MobileAcademy
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
Johnny Sung
 
Introduction to VueJS & Vuex
Introduction to VueJS & Vuex
Bernd Alter
 
JUnit 5 - The Next Generation
JUnit 5 - The Next Generation
Kostadin Golev
 
Clean code
Clean code
ifnu bima
 
Clean Code Principles
Clean Code Principles
YeurDreamin'
 
Clean Code
Clean Code
Dmytro Turskyi
 
Introduction to kotlin and OOP in Kotlin
Introduction to kotlin and OOP in Kotlin
vriddhigupta
 
Swift Programming Language
Swift Programming Language
Giuseppe Arici
 
JUNit Presentation
JUNit Presentation
Animesh Kumar
 
Angular Advanced Routing
Angular Advanced Routing
Laurent Duveau
 
大家來學GObject
大家來學GObject
Shu-Yu Fu
 
React and redux
React and redux
Mystic Coders, LLC
 
Angular routing
Angular routing
Sultan Ahmed
 
Angular Unit Testing
Angular Unit Testing
Alessandro Giorgetti
 
Spring boot Introduction
Spring boot Introduction
Jeevesh Pandey
 
OOP with Java - Continued
OOP with Java - Continued
Hitesh-Java
 
Clean Code JavaScript
Clean Code JavaScript
Riza Fahmi
 
Kotlin presentation
Kotlin presentation
MobileAcademy
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
Johnny Sung
 
Introduction to VueJS & Vuex
Introduction to VueJS & Vuex
Bernd Alter
 
JUnit 5 - The Next Generation
JUnit 5 - The Next Generation
Kostadin Golev
 
Clean Code Principles
Clean Code Principles
YeurDreamin'
 
Introduction to kotlin and OOP in Kotlin
Introduction to kotlin and OOP in Kotlin
vriddhigupta
 
Swift Programming Language
Swift Programming Language
Giuseppe Arici
 
Angular Advanced Routing
Angular Advanced Routing
Laurent Duveau
 
大家來學GObject
大家來學GObject
Shu-Yu Fu
 
Spring boot Introduction
Spring boot Introduction
Jeevesh Pandey
 
OOP with Java - Continued
OOP with Java - Continued
Hitesh-Java
 

Similar to Clean code in JavaScript (20)

Good Coding Practices with JavaScript
Good Coding Practices with JavaScript
🏁 Pierre-Henry Soria 💡
 
OOP Best Practices in JavaScript
OOP Best Practices in JavaScript
Haim Michael
 
Clean Code. An Agile Guide to Software Craft Kameron H.
Clean Code. An Agile Guide to Software Craft Kameron H.
komvjzfjj621
 
Clean code and code smells
Clean code and code smells
Md. Aftab Uddin Kajal
 
Writing clean code
Writing clean code
Angel Garcia Olloqui
 
Clean code
Clean code
Khou Suylong
 
Beyond PITS, Functional Principles for Software Architecture
Beyond PITS, Functional Principles for Software Architecture
Jayaram Sankaranarayanan
 
JavaScript Abstraction
JavaScript Abstraction
☆ Milan Adamovsky ☆
 
379008-rc217-functionalprogramming
379008-rc217-functionalprogramming
Luis Atencio
 
Wakanday JS201 Best Practices
Wakanday JS201 Best Practices
Juergen Fesslmeier
 
Clean Code - Writing code for human
Clean Code - Writing code for human
NETKO Solution
 
Does your code spark joy? Refactoring techniques to make your life easier.
Does your code spark joy? Refactoring techniques to make your life easier.
Juciellen Cabrera
 
Clean Code (David Frame) - PHPBelfast Meetup 22/02/24
Clean Code (David Frame) - PHPBelfast Meetup 22/02/24
davidgrantframe
 
From object oriented to functional domain modeling
From object oriented to functional domain modeling
Codemotion
 
Cleaner Code - CodeStock 2019 Edition
Cleaner Code - CodeStock 2019 Edition
Dave Fancher
 
From object oriented to functional domain modeling
From object oriented to functional domain modeling
Mario Fusco
 
Functional Programming 101 for Java 7 Developers
Functional Programming 101 for Java 7 Developers
Jayaram Sankaranarayanan
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
Scott Wlaschin
 
[DevDay2018] Let’s all get along. Clean Code please! - By: Christophe K. Ngo,...
[DevDay2018] Let’s all get along. Clean Code please! - By: Christophe K. Ngo,...
DevDay Da Nang
 
Javascript Programming according to Industry Standards.pptx
Javascript Programming according to Industry Standards.pptx
MukundSonaiya1
 
OOP Best Practices in JavaScript
OOP Best Practices in JavaScript
Haim Michael
 
Clean Code. An Agile Guide to Software Craft Kameron H.
Clean Code. An Agile Guide to Software Craft Kameron H.
komvjzfjj621
 
Beyond PITS, Functional Principles for Software Architecture
Beyond PITS, Functional Principles for Software Architecture
Jayaram Sankaranarayanan
 
379008-rc217-functionalprogramming
379008-rc217-functionalprogramming
Luis Atencio
 
Clean Code - Writing code for human
Clean Code - Writing code for human
NETKO Solution
 
Does your code spark joy? Refactoring techniques to make your life easier.
Does your code spark joy? Refactoring techniques to make your life easier.
Juciellen Cabrera
 
Clean Code (David Frame) - PHPBelfast Meetup 22/02/24
Clean Code (David Frame) - PHPBelfast Meetup 22/02/24
davidgrantframe
 
From object oriented to functional domain modeling
From object oriented to functional domain modeling
Codemotion
 
Cleaner Code - CodeStock 2019 Edition
Cleaner Code - CodeStock 2019 Edition
Dave Fancher
 
From object oriented to functional domain modeling
From object oriented to functional domain modeling
Mario Fusco
 
Functional Programming 101 for Java 7 Developers
Functional Programming 101 for Java 7 Developers
Jayaram Sankaranarayanan
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
Scott Wlaschin
 
[DevDay2018] Let’s all get along. Clean Code please! - By: Christophe K. Ngo,...
[DevDay2018] Let’s all get along. Clean Code please! - By: Christophe K. Ngo,...
DevDay Da Nang
 
Javascript Programming according to Industry Standards.pptx
Javascript Programming according to Industry Standards.pptx
MukundSonaiya1
 
Ad

More from Mathieu Breton (8)

TDD in Javascript
TDD in Javascript
Mathieu Breton
 
Meet VueJs
Meet VueJs
Mathieu Breton
 
FalcorJS
FalcorJS
Mathieu Breton
 
BDD in Javascript
BDD in Javascript
Mathieu Breton
 
NodeJS Spring style Inversifyjs
NodeJS Spring style Inversifyjs
Mathieu Breton
 
Rollup.js
Rollup.js
Mathieu Breton
 
Présentation de Dart
Présentation de Dart
Mathieu Breton
 
JavaScript the-next-big...bytecode
JavaScript the-next-big...bytecode
Mathieu Breton
 
Ad

Recently uploaded (20)

ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
Securing Account Lifecycles in the Age of Deepfakes.pptx
Securing Account Lifecycles in the Age of Deepfakes.pptx
FIDO Alliance
 
Cracking the Code - Unveiling Synergies Between Open Source Security and AI.pdf
Cracking the Code - Unveiling Synergies Between Open Source Security and AI.pdf
Priyanka Aash
 
Hyderabad MuleSoft In-Person Meetup (June 21, 2025) Slides
Hyderabad MuleSoft In-Person Meetup (June 21, 2025) Slides
Ravi Tamada
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
UserCon Belgium: Honey, VMware increased my bill
UserCon Belgium: Honey, VMware increased my bill
stijn40
 
Mastering AI Workflows with FME by Mark Döring
Mastering AI Workflows with FME by Mark Döring
Safe Software
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
Wenn alles versagt - IBM Tape schützt, was zählt! Und besonders mit dem neust...
Wenn alles versagt - IBM Tape schützt, was zählt! Und besonders mit dem neust...
Josef Weingand
 
10 Key Challenges for AI within the EU Data Protection Framework.pdf
10 Key Challenges for AI within the EU Data Protection Framework.pdf
Priyanka Aash
 
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Safe Software
 
A Constitutional Quagmire - Ethical Minefields of AI, Cyber, and Privacy.pdf
A Constitutional Quagmire - Ethical Minefields of AI, Cyber, and Privacy.pdf
Priyanka Aash
 
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
Quantum AI: Where Impossible Becomes Probable
Quantum AI: Where Impossible Becomes Probable
Saikat Basu
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
The Future of Product Management in AI ERA.pdf
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik
 
The Growing Value and Application of FME & GenAI
The Growing Value and Application of FME & GenAI
Safe Software
 
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
Earley Information Science
 
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
digitaljignect
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
Securing Account Lifecycles in the Age of Deepfakes.pptx
Securing Account Lifecycles in the Age of Deepfakes.pptx
FIDO Alliance
 
Cracking the Code - Unveiling Synergies Between Open Source Security and AI.pdf
Cracking the Code - Unveiling Synergies Between Open Source Security and AI.pdf
Priyanka Aash
 
Hyderabad MuleSoft In-Person Meetup (June 21, 2025) Slides
Hyderabad MuleSoft In-Person Meetup (June 21, 2025) Slides
Ravi Tamada
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
UserCon Belgium: Honey, VMware increased my bill
UserCon Belgium: Honey, VMware increased my bill
stijn40
 
Mastering AI Workflows with FME by Mark Döring
Mastering AI Workflows with FME by Mark Döring
Safe Software
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
Wenn alles versagt - IBM Tape schützt, was zählt! Und besonders mit dem neust...
Wenn alles versagt - IBM Tape schützt, was zählt! Und besonders mit dem neust...
Josef Weingand
 
10 Key Challenges for AI within the EU Data Protection Framework.pdf
10 Key Challenges for AI within the EU Data Protection Framework.pdf
Priyanka Aash
 
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Smarter Aviation Data Management: Lessons from Swedavia Airports and Sweco
Safe Software
 
A Constitutional Quagmire - Ethical Minefields of AI, Cyber, and Privacy.pdf
A Constitutional Quagmire - Ethical Minefields of AI, Cyber, and Privacy.pdf
Priyanka Aash
 
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
Quantum AI: Where Impossible Becomes Probable
Quantum AI: Where Impossible Becomes Probable
Saikat Basu
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
The Future of Product Management in AI ERA.pdf
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik - Passionate Tech Enthusiast
Raman Bhaumik
 
The Growing Value and Application of FME & GenAI
The Growing Value and Application of FME & GenAI
Safe Software
 
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
Earley Information Science
 
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
digitaljignect
 

Clean code in JavaScript

  • 5. There are only two hard things inThere are only two hard things in Computer Science: cache invalidationComputer Science: cache invalidation and naming things.and naming things. There are only two hard things inThere are only two hard things in Computer Science: cache invalidationComputer Science: cache invalidation and naming things.and naming things. “ Phil Karlton
  • 6. Use meaningful and pronounceable variable namesUse meaningful and pronounceable variable names const yyyymmdstr = moment().format('YYYY/MM/DD'); const yearMonthDay = moment().format('YYYY/MM/DD');
  • 7. Use the same vocabulary for the same type of variableUse the same vocabulary for the same type of variable getUserInfo(); getClientData(); getCustomerRecord(); getUser();
  • 8. Use searchable namesUse searchable names // What the heck is 525600 for? for (let i = 0; i < 525600; i++) { runCronJob(); } // Declare them as capitalized `const` globals. const MINUTES_IN_A_YEAR = 525600; for (let i = 0; i < MINUTES_IN_A_YEAR; i++) { runCronJob(); }
  • 9. Keep convention in mindKeep convention in mind class AnimalSoSweet {} // UpperCamelCase let anAnimal = new AnimalSoSweet(); // LowerCamlCase function sendARequest(requestToSend){};// LowerCamlCase const NB_MS_IN_HOUR = 3600; // SCREAMING_SNAKE_CASE
  • 10. Use explanatory variablesUse explanatory variables const cityStateRegex = /^(.+)[,s]+(.+?)s*(d{5})?$/; saveCityState( cityStateRegex.match(cityStateRegex)[1], cityStateRegex.match(cityStateRegex)[2] ); const cityStateRegex = /^(.+)[,s]+(.+?)s*(d{5})?$/; const match = cityStateRegex.match(cityStateRegex) const city = match[1]; const state = match[2]; saveCityState(city, state);
  • 11. Avoid Mental MappingAvoid Mental Mapping const locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((l) => { doStuff(); doSomeOtherStuff(); // ... // ... // ... // Wait, what is `l` for again? dispatch(l); }); const locations = ['Austin', 'New York', 'San Francisco']; locations.forEach((location) => { doStuff(); doSomeOtherStuff(); // ... // ... // ... dispatch(location); });
  • 12. Don't add unneeded contextDon't add unneeded context const Car = { carMake: 'Honda', carModel: 'Accord', carColor: 'Blue' }; function paintCar(car) { car.carColor = 'Red'; } const Car = { make: 'Honda', model: 'Accord', color: 'Blue' }; function paintCar(car) { car.color = 'Red'; }
  • 13. Short-circuiting is cleaner than conditionalsShort-circuiting is cleaner than conditionals function createMicrobrewery(name) { let breweryName; if (name) { breweryName = name; } else { breweryName = 'Hipster Brew Co.'; } } function createMicrobrewery(name) { const breweryName = name || 'Hipster Brew Co.' }
  • 15. Function arguments (2 or fewer ideally)Function arguments (2 or fewer ideally) function createMenu(title, body, buttonText, cancellable) { // ... } const menuConfig = { title: 'Foo', body: 'Bar', buttonText: 'Baz', cancellable: true } function createMenu(menuConfig) { // ... }
  • 16. Functions should do one thing (Small !)Functions should do one thing (Small !) function emailClients(clients) { clients.forEach(client => { const clientRecord = database.lookup(client); if (clientRecord.isActive()) { email(client); } }); } function emailClients(clients) { clients .filter(isClientActive) .forEach(email); } function isClientActive(client) { const clientRecord = database.lookup(client); return clientRecord.isActive(); }
  • 17. Don't use flags as function parametersDon't use flags as function parameters function createFile(name, temp) { if (temp) { fs.create('./temp/' + name); } else { fs.create(name); } } function createFile(name) { fs.create(name); } function createTempFile(name) { createFile('./temp/' + name); }
  • 18. Function names should say what they doFunction names should say what they do function dateAdd(date, month) { // ... } const date = new Date(); /* It's hard to to tell from the function name what is added */ dateAdd(date, 1); function dateAddMonth(date, month) { // ... } const date = new Date(); dateAddMonth(date, 1);
  • 19. Function should not have side effectFunction should not have side effect let name = 'Ryan McDermott'; function splitIntoFirstAndLastName() { name = name.split(' '); } splitIntoFirstAndLastName(); function splitIntoFirstAndLastName(name) { return name.split(' '); } const name = 'Ryan McDermott' const newName = splitIntoFirstAndLastName(name);
  • 20. Use default arguments instead of short circuitingUse default arguments instead of short circuiting function writeForumComment(subject, body) { subject = subject || 'No Subject'; body = body || 'No text'; } function writeForumComment( subject = 'No subject', body = 'No text') { // ... }
  • 21. Encapsulate conditionalsEncapsulate conditionals if (fsm.state === 'fetching' && isEmpty(listNode)) { // ... } function shouldShowSpinner(fsm, listNode) { return fsm.state === 'fetching' && isEmpty(listNode); } if (shouldShowSpinner(fsmInstance, listNodeInstance)) { // ... }
  • 22. Sort correctly callers and calleeSort correctly callers and callee function doVerySpecificThing(){ //... } function doSpecificThing(){ //... doVerySpecificThing(); } function doThing(){ //... doSpecificThing(); } function doThing(){ //... doSpecificThing(); } function doSpecificThing(){ //... doVerySpecificThing(); } function doVerySpecificThing(){ //... }
  • 23. Prefer functional programming over imperativePrefer functional programming over imperative const programmerOutput = [ { name: 'Uncle Bobby', linesOfCode: 500 }, { name: 'Suzie Q', linesOfCode: 1500 } //.... ]; let totalOutput = 0; for (let i = 0; i < programmerOutput.length; i++) { totalOutput += programmerOutput[i].linesOfCode; } const programmerOutput = [ { name: 'Uncle Bobby', linesOfCode: 500 }, { name: 'Suzie Q', linesOfCode: 1500 } //.... ]; const totalOutput = programmerOutput .map((programmer) => programmer.linesOfCode) .reduce((acc, linesOfCode) => acc + linesOfCode, 0);
  • 24. Prefer polymorphism over lot of conditionalsPrefer polymorphism over lot of conditionals class Airplane { // ... getCruisingAltitude() { switch (this.type) { case '777': return this.getMaxAltitude() - this.getPassengerCount(); case 'Air Force One': return this.getMaxAltitude(); case 'Cessna': return this.getMaxAltitude() - this.getFuelExpenditure(); } } } class Airplane {} class Boeing777 extends Airplane { getCruisingAltitude() { return this.getMaxAltitude() - this.getPassengerCount(); } } class AirForceOne extends Airplane { getCruisingAltitude() { return this.getMaxAltitude(); } }
  • 25. Never everNever ever lets dead or commented code !!!lets dead or commented code !!! // function oldRequestModule(url) { // ... // } function newRequestModule(url) { // ... } const req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io'); function newRequestModule(url) { // ... } const req = newRequestModule; inventoryTracker('apples', req, 'www.inventory-awesome.io');
  • 27. SSingle responsibilityingle responsibility OOpen-closedpen-closed LLiskov substitutioniskov substitution IInterface segregationnterface segregation DDependency injectionependency injection SOLIDSOLID principlesprinciples en.wikipedia.org/wiki/SOLID_(object-oriented_design)
  • 28. Single Responsibility Principle (Single Responsibility Principle (SSRP)RP) class UserService { saveUser(user){ eventEmmitter.dispatch(ADD_USER, user); return db.exec('INSERT VALUES ...', user); } } class UserResource { //... save(user){ return db.exec('INSERT VALUES ...', user); } } class UserService { //... saveUser(user){ eventEmmitter.dispatch(ADD_USER, user); return userRessource.save(user) } } "There should never be more than one reason for a class to change"
  • 29. Open/Closed Principle (Open/Closed Principle (OOCP)CP) class ExpenseController { constructor() {} addNewExpense(expense) { if (this.validateExpense(expense)){ expenseService.save(expense); } } validateExpense (expense){ return !!expense.description; } } class UserAuth { constructor(user) { this.user = user; } verifyCredentials() { // ... } } class ExpenseController { constructor(validators) {this.validators=validators;} addNewExpense(expense) { if (this.validateExpense(expense)){ expenseService.save(expense); } } validateExpense (expense){ return this.validators.every(validator => { return validator.isValid(expense)); }); } } "open for extension, but closed for modification"
  • 30. Liskov substitution principle (Liskov substitution principle (LLSP)SP) class Rectangle { //... setWidth(width) { this.width = width; } setHeight(height) { this.height = height; } getArea() { return this.width * this.height; } } class Square extends Rectangle { // ... setWidth(width) { this.width = width; this.height = width; } setHeight(height) { this.width = height; this.height = height; } } function renderLargeRectangles(rectangles) { rectangles.forEach((rectangle) => { rectangle.setWidth(4); rectangle.setHeight(5); const area = rectangle.getArea();//Will return 25 for Square. Should be 20. rectangle.render(area); }); } const rectangles = [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles(rectangles);
  • 31. Liskov substitution principle (Liskov substitution principle (LLSP)SP) class Shape { setColor(color) { // ... } render(area) { // ... } } class Rectangle extends Shape { constructor() { super(); this.width = 0; this.height = 0; } setWidth(width) { this.width = width; } setHeight(height) { this.height = height; } getArea() { return this.width * this.height; } } class Square extends Shape { constructor() { super(); this.length = 0; } setLength(length) { this.length = length; } getArea() { return this.length * this.length; } } function renderLargeShapes(shapes) { shapes.forEach((shape) => { switch (shape.constructor.name) { case 'Square': shape.setLength(5); break; case 'Rectangle': shape.setWidth(4); shape.setHeight(5); } const area = shape.getArea(); shape.render(area); }); }
  • 32. Interface segregation principle (Interface segregation principle (IISP)SP) class ACar { run(){ throw new Error('SubType of car should implement run'); } fillFuel(){ throw new Error('SubType of car should implement fillFuel'); } } class MyOldCar extends ACar{ run(){ // run ... } fillFuel(){ // handle fillFuel } } class MyElectricCar extends ACar{ run(){ // run ... } fillFuel(){ // Not necessary } } "Clients should not be forced to depend upon interfaces that they do not use."
  • 33. Interface segregation principle (Interface segregation principle (IISP)SP) class ACar { run(){ throw new Error('SubType of car should implement run'); } } const FuelCar = (Superclass) => class extends Superclass { fillFuel() { throw new Error('SubType of FuelCar should implement fillFuel'); } } class MyOldCar extends FuelCar(ACar){ run(){ // run ... } fillFuel(){ // handle fillFuel } } const ElectricCar = (Superclass) => class extends Superclass { reload() { throw new Error('SubType of ElectricCar should implement reload'); } } class MyElectricCar extends ElectricCar(ACar){ run(){ // run ... } reload(){ // handle reload } } "Clients should not be forced to depend upon interfaces that they do not use."
  • 34. Dependency Inversion Principle (Dependency Inversion Principle (DDIP)IP) "1. High-level modules should not depend on low-level modules. Both should depend on abstractions. 2. Abstractions should not depend upon details. Details should depend on abstractions." class UserController { constructor(){ this.userService = new UserService(); } save(user){ this.userService.save(user); } } class UserController { constructor(userService){ this.userService = userService; } save(user){ this.userService.save(user); } }
  • 35. Use method chainingUse method chaining "1. High-level modules should not depend on low-level modules. Both should depend on abstractions. 2. Abstractions should not depend upon details. Details should depend on abstractions." class User { constructor(name, age){ this.name = name; this.age = age; } setName(name){ this.name = name; } setAge(age){ this.age = age; } } const user = new User(); user.setName('Mathieu'); user.setAge('28'); class User { constructor(name, age){ this.name = name; this.age = age; } setName(name){ this.name = name; return this; } setAge(age){ this.age = age; return this; } } const user = new User() .setName('Mathieu') .setAge('28');
  • 37. Only comment things that have business logic complexity.Only comment things that have business logic complexity. function hashIt(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; } } "Comments are an apology, not a requirement. Good code mostly documents itself." function hashIt(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; } }
  • 38. Bad commentsBad comments /** * 2016-12-20: Removed monads, didn't understand them (RM) * 2016-10-01: Improved using special monads (JP) * 2016-02-03: Removed type-checking (LI) * 2015-03-14: Added combine with type-checking (JR) */ //////////////////////////////////////////////////////////////////////////////// // Scope Model Instantiation //////////////////////////////////////////////////////////////////////////////// $scope.model = { menu: 'foo', nav: 'bar' }; while (toto < MAX_VALUES){ if (test > MIN_VALUES){ } // if } // while