Source Code
Syntax
Source Code sollte den modernen Standards der jeweiligen Sprache entsprechen.
Linting & Formatting
Um unnötige Diskussionen über stilistische Entscheidungen zu vermeiden, soll Prettier verwendet werden. Javascript und Typescript soll außerdem mit ESLint gelintet werden.
Semantik
Semantic Elements sollen sinnvoll und zweckmäßig eingesetzt werden. Dazu gehören unter anderem: article
, aside
, figcaption
, figure
, footer
, header
, main
, nav
, section
Namensgebung
Damit Source Code verständlich und durchsuchbar ist, müssen sämtliche Variablen benannt werden.
Schlecht
setTimeout(takeOff, 86400000)
Gut
const MillisecondsPerDay = 86400000
setTimeout(takeOff, MillisecondsPerDay)
Namen sollen eine klare Beziehung zum Inhalt haben und zum Verständnis des Source Codes beitragen.
Schlecht
const n = 'John Doe'
Gut
const fullName = 'John Doe'
Auch wenn der Kontext zum Verständnis der Namensgebung beiträgt muss diese explizit, nicht implizit sein.
Schlecht
const bandMembers = ['John', 'Paul', 'George', 'Ringo']
bandMembers.forEach((m) => {
sendOnStage(m)
})
Gut
const bandMembers = ['John', 'Paul', 'George', 'Ringo']
bandMembers.forEach((member) => {
sendOnStage(member)
})
Funktionen
Ein-Zweck Funktionen
Funktionen sollen möglichst nur eine Aufgabe erfüllen. Komplexe Funktionen sind generell schwerer zu verstehen, zu testen und zu überarbeiten.
Schlecht
function emailClients(clients) {
clients.forEach((client) => {
const clientRecord = database.lookup(client)
if (clientRecord.isActive()) {
email(client)
}
})
}
Gut
function emailActiveClients(clients) {
clients.filter(isActiveClient).forEach(email)
}
function isActiveClient(client) {
const clientRecord = database.lookup(client)
return clientRecord.isActive()
}
Selbstdokumentierend
Die Benahmung von Funktionien soll möglichst selbst dokumentierend sein.
Schlecht
function addToArray(arr, item) {
// ...
}
const fruit = 'Banana'
addToArray([], fruit)
Gut
function addFruitToBasket(fruit, basket) {
// ...
}
const basket = ['Strawberry', 'Apple']
const fruit = 'Banana'
addFruitToBasket(fruit, basket)
Duplizierter Code
Funktionen sollen, wenn möglich, sinnvoll zusammen gefasst werden.
Schlecht
function showProfessionalList(professionals) {
professionals.forEach((professional) => {
const age = professional.getAge()
const startNumber = professional.getStartNumber()
const team = professional.getTeam()
const data = {
age,
startNumber,
team,
}
render(data)
})
}
function showAmateurList(amateurs) {
amateurs.forEach((amateur) => {
const age = amateur.getAge()
const startNumber = amateur.getStartNumber()
const entryFeePaid = amateur.hasPaidEntryFee()
const data = {
age,
startNumber,
entryFeePaid,
}
render(data)
})
}
Gut
function showAthletesList(athletes) {
athletes.forEach((athlete) => {
const age = athlete.getAge()
const startNumber = athlete.getStartNumber()
const data = {
age,
startNumber,
}
switch (athlete.type) {
case 'professional':
data.team = athlete.getTeam()
break
case 'amateur':
data.entryFeePaid = athlete.hasPaidEntryFee()
break
}
render(data)
})
}
Negative Conditionals
Negative Conditionals verschlechtern die Lesbarkeit unnötigerweise.
Schlecht
function isNotVisible(element) {
// ...
}
if (!isNotVisible(element)) {
// ...
}
Gut
function isVisible(element) {
// ...
}
if (isVisible(element)) {
// ...
}
Concurrency
Async/Await
Async/Await Funktionen verbessern die Lesbarkeit und Performance.
Schlecht
function logFetch(url) {
return fetch(url)
.then((response) => response.text())
.then((text) => {
console.log(text)
})
.catch((error) => {
console.error('fetch failed', error)
})
}
Gut
async function logFetch(url) {
try {
const response = await fetch(url)
console.log(await response.text())
} catch (error) {
console.error('fetch failed', error)
}
}
Error Handling
Fehlermeldungen
Fehlermeldungen sollen generell nicht einfach nur via console.log
verarbeitet werden.
Schlecht
try {
errorProneFunction()
} catch (error) {
console.log(error)
}
Gut
try {
errorProneFunction()
} catch (error) {
console.error(error)
reportError(error)
}
Rejected Promises
async function logFetch(url) {
try {
const response = await fetch(url)
console.log(await response.text())
} catch (error) {
console.log(error)
}
}
Gut
async function logFetch(url) {
try {
const response = await fetch(url)
console.log(await response.text())
} catch (error) {
console.error('fetch failed', error)
reportError(error)
}
}
Comments
Komplexe Logik
Source Code ist durch klare Strukturen und Namensgebung selbstdokumentierend. Komplexer Code sollte trotzdem mit kurzen Hinweisen versehen werden.
Schlecht
function hashIt(data) {
// The hash
let hash = 0
// Loop through every character in data
for (let i = 0; i < data.length; i++) {
// Get char code
const char = data.charCodeAt(i)
// Create hash
hash = (hash << 5) - hash + char
// Convert to 32-bit integer
hash &= hash
}
}
Gut
function hashIt(data) {
let hash = 0
for (let i = 0; i < data.length; i++) {
const char = data.charCodeAt(i)
hash = (hash << 5) - hash + char
// Convert to 32-bit integer
hash &= hash
}
}
Ungenutzter Code
Ungenutzer/veralteter Code kann via Version Control
gespeichert werden, statt auskommentiert im Source Code zu stehen.
Schlecht
doThings()
// doOtherThings()
// doSomeMoreThings()
Gut
doThings()