Clean Code: Funktionen (in Javascript)
Sind Sie es leid, mit komplexen, schwer verständlichen Funktionen in Ihrer Codebasis zu kämpfen? Möchten Sie Funktionen schreiben, die besser wartbar, wiederverwendbar und weniger fehleranfällig sind? Wenn ja, dann müssen Sie sich mit „Clean Code: Functions“ vertraut machen. Indem Sie die im Buch „Clean Code“ von Robert C. Martin beschriebenen Best Practices befolgen, können Sie lernen, Funktionen zu schreiben, die einfacher zu lesen, zu testen und zu warten sind. In diesem Blogbeitrag werden wir die Schlüsselkonzepte sauberer Codefunktionen untersuchen und Ihnen praktische Tipps und Beispiele zur Verfügung stellen, die Ihnen helfen, diese Konzepte in Ihrem eigenen Code zu implementieren. Mit unserer Hilfe können Sie Ihre Programmierkenntnisse auf die nächste Stufe heben und Funktionen schreiben, mit denen es Spaß macht zu arbeiten. Sind Sie also bereit, mehr über Clean-Code-Funktionen zu erfahren? Tauchen wir ein!
Inhaltsverzeichnis
· Kleine Funktionen sind besser als große
· Funktionen sollten eine Sache tun
· Funktionen sollten aussagekräftige Namen haben
· Funktionen sollten eine begrenzte Anzahl von Argumenten haben
· Funktionen sollten keine Seiteneffekte haben
· Funktionen sollten sich nicht auf globale Variablen verlassen
· Funktionen sollten es nicht sein Tief verschachtelt
· Verwenden Sie Ausnahmen, keine Fehlercodes
· Fazit
Kleine Funktionen sind besser als große
Kleine Funktionen sind leichter zu lesen und zu verstehen, da sie normalerweise eine Sache tun und einen klaren Zweck haben. Dies erleichtert auch das Testen und Warten, da weniger Code überprüft oder geändert werden muss. Große Funktionen hingegen können komplexer und schwerer verständlich sein, was zu Bugs oder Fehlern führen kann.
// Large function
function processOrders(orders) {
const total = orders.reduce((acc, order) => acc + order.price, 0);
const orderIds = orders.map(order => order.id);
const orderCount = orders.length;
const orderSummary = `You have ${orderCount} orders with IDs ${orderIds.join(', ')} for a total of $${total}.`;
console.log(orderSummary);
return orderSummary;
}
// --------------------------------------------------------------
// Refactored into smaller functions
function getTotalPrice(orders) {
return orders.reduce((acc, order) => acc + order.price, 0);
}
function getOrderIds(orders) {
return orders.map(order => order.id);
}
function getOrderCount(orders) {
return orders.length;
}
function generateOrderSummary(orders) {
const total = getTotalPrice(orders);
const orderIds = getOrderIds(orders);
const orderCount = getOrderCount(orders);
return `You have ${orderCount} orders with IDs ${orderIds.join(', ')} for a total of $${total}.`;
}
function logOrderSummary(orders) {
const orderSummary = generateOrderSummary(orders);
console.log(orderSummary);
return orderSummary;
}
Die getTotalPrice()Funktion nimmt ein Array von Bestellungen und gibt ihren Gesamtpreis zurück, indem sie die reduce()Funktion verwendet, um den Preis jeder Bestellung zu summieren. Die getOrderIds()Funktion nimmt ein Array von Bestellungen und gibt ein Array ihrer IDs zurück, indem sie die map()Funktion verwendet. Die getOrderCount()Funktion nimmt ein Array von Bestellungen und gibt ihre Anzahl mithilfe der lengthEigenschaft zurück. Schließlich generateOrderSummary()nimmt die Funktion ein Array von Aufträgen und verwendet die drei kleineren Funktionen, um eine Zusammenfassungszeichenfolge zu generieren. Die logOrderSummary()Funktion nimmt ein Array von Aufträgen entgegen und protokolliert die Zusammenfassungszeichenfolge in der Konsole.
Funktionen sollten eine Sache tun
Jede Funktion sollte einen klaren und eindeutigen Zweck haben. Wenn eine Funktion mehrere Aufgaben erfüllt, kann es schwieriger werden, sie zu verstehen, zu testen und zu warten. Indem wir eine größere Aufgabe in kleinere Funktionen zerlegen, können wir besser lesbaren und wartbaren Code erstellen.
// Function that performs multiple tasks
function processUserInput(input) {
const inputLines = input.split('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n');
const trimmedLines = inputLines.map(line => line.trim());
const nonEmptyLines = trimmedLines.filter(line => line !== '');
const formattedLines = nonEmptyLines.map(line => `> ${line}`);
return formattedLines.join('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n');
}
// --------------------------------------------------------------
// Refactored into smaller functions
function splitInput(input) {
return input.split('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n');
}
function trimLines(lines) {
return lines.map(line => line.trim());
}
function removeEmptyLines(lines) {
return lines.filter(line => line !== '');
}
function formatLines(lines) {
return lines.map(line => `> ${line}`);
}
function joinLines(lines) {
return lines.join('\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n');
}
function processUserInput(input) {
const lines = splitInput(input);
const trimmedLines = trimLines(lines);
const nonEmptyLines = removeEmptyLines(trimmedLines);
const formattedLines = formatLines(nonEmptyLines);
return joinLines(formattedLines);
}
Die splitInput()Funktion nimmt einen String und verwendet die split()Methode, um ihn in ein Array von Zeilen aufzuteilen. Die trimLines()Funktion nimmt ein Array von Zeilen und verwendet die map()Methode, um alle Leerzeichen am Anfang und am Ende jeder Zeile zu entfernen. Die removeEmptyLines()Funktion nimmt ein Array von Zeilen und verwendet die filter()Methode, um alle leeren Zeilen zu entfernen. Die formatLines()Funktion nimmt ein Array von Zeilen und verwendet die Methode, um am Anfang jeder Zeile map()ein Zeichen hinzuzufügen . >Die joinLines()Funktion nimmt ein Array von Zeilen und verwendet die join()Methode, um sie zu einer einzelnen Zeichenfolge zu verbinden, die durch Zeilenumbrüche getrennt ist. Schließlich processUserInput()verwendet die Funktion die kleineren Funktionen, um die Eingabezeichenfolge zu verarbeiten.
Funktionen sollten beschreibende Namen haben
Funktionsnamen sollten genau beschreiben, was die Funktion tut, und leicht verständlich sein, ohne dass Sie die Implementierung der Funktion lesen müssen. Ein aussagekräftiger Funktionsname kann helfen, den Code selbsterklärender zu machen und die Notwendigkeit von Kommentaren zu reduzieren.
// Function with a vague name
function processData(data) {
// ...
}
// --------------------------------------------------------------
// Refactored with a descriptive name
function processUserData(userData) {
// ...
}
Funktionen sollten eine begrenzte Anzahl von Argumenten haben
Funktionen, die eine große Anzahl von Argumenten benötigen, können schwieriger zu verwenden, zu verstehen und zu testen sein. Versuchen Sie, die Anzahl der Argumente nach Möglichkeit unter drei oder vier zu halten. Eine Möglichkeit, die Anzahl der Argumente zu reduzieren, besteht darin, sie als einzelnes Objekt oder als einzelne Datenstruktur zu übergeben.
// Function with too many arguments
function createPerson(name, age, address, phone, email) {
// ...
}
// --------------------------------------------------------------
// Refactored to use an object instead
function createPerson(personData) {
// ...
}
// Now, we can pass an object with properties for name, age, address, phone, and email:
const personData = {
name: 'John Doe',
age: 30,
address: '123 Main St',
phone: '555-555-1234',
email: '[email protected]'
};
const person = createPerson(personData);
Funktionen sollten keine Nebenwirkungen haben
Ein Nebeneffekt tritt auf, wenn eine Funktion einen Zustand außerhalb ihres eigenen Gültigkeitsbereichs ändert. Nebenwirkungen können das Testen und Begründen des Verhaltens der Funktion erschweren und können auch zu unerwartetem Verhalten führen. Funktionen sollten nur mit ihren eigenen Parametern und lokalen Variablen arbeiten und keinen Zustand außerhalb ihres Gültigkeitsbereichs ändern.
// Example with side effects
let arr = [1, 2, 3];
function popLastElement() {
arr.pop(); // modifies the external state of `arr`
}
popLastElement();
console.log(arr); // Output: [1, 2]
// --------------------------------------------------------------
// Example without side effects
function getLastElement(arr) {
return arr[arr.length - 1]; // returns a new value without modifying the input
}
let arr = [1, 2, 3];
let lastElement = getLastElement(arr);
console.log(lastElement); // Output: 3
Funktionen sollten sich nicht auf globale Variablen verlassen
Globale Variablen erschweren das Verständnis und Testen von Funktionen und können zu unerwartetem Verhalten führen. Funktionen sollten nur mit ihren eigenen Parametern und lokalen Variablen arbeiten und sich nicht auf den globalen Zustand verlassen. Dies erleichtert auch die Wiederverwendung der Funktion in verschiedenen Kontexten.
// Example relying on global state
let x = 0;
function increment() {
x++;
}
increment();
console.log(x); // Output: 1
// --------------------------------------------------------------
// Example without relying on global state
function increment(x) {
return x + 1;
}
let y = 0;
y = increment(y);
console.log(y); // Output: 1
Funktionen sollten nicht zu tief verschachtelt sein
Tief verschachtelte Funktionen können schwerer zu lesen und zu verstehen sein und zu komplexen Kontrollstrukturen führen. Funktionen sollten so strukturiert sein, dass der Steuerungsfluss leicht verständlich ist, ohne dass man sich Gedanken über mehrere Ebenen verschachtelter Funktionen machen muss.
// Example with deeply nested functions
function add(a, b) {
function increment(x) {
return x + 1;
}
let c = increment(a);
let d = increment(b);
return c + d;
}
console.log(add(1, 2)); // Output: 5
// --------------------------------------------------------------
// Example with flatter function structure
function increment(x) {
return x + 1;
}
function add(a, b) {
let c = increment(a);
let d = increment(b);
return c + d;
}
console.log(add(1, 2)); // Output: 5
Verwenden Sie Ausnahmen, keine Fehlercodes
Fehlercodes können das Nachvollziehen des Codes erschweren und zu komplexen Kontrollstrukturen führen. Ausnahmen ermöglichen einen natürlicheren Kontrollfluss und eine einfachere Fehlerbehandlung. Funktionen sollten Ausnahmen auslösen, um Fehler oder unerwartetes Verhalten anzuzeigen, anstatt Fehlercodes oder -werte zurückzugeben.
// Example with error code
function divide(a, b) {
if (b === 0) {
return -1; // error code for divide by zero
}
return a / b;
}
let result = divide(4, 0);
if (result === -1) {
console.log("Error: Divide by zero"); // error handling with error code
}
// --------------------------------------------------------------
// Example with exception
function divide(a, b) {
if (b === 0) {
throw new Error("Divide by zero"); // throws an exception
}
return a / b;
}
try {
let result = divide(4, 0);
} catch (e) {
console.log("Error: " + e.message); // error handling with exception
}
Abschluss
Zusammenfassend ist es wichtig, beim Schreiben von Funktionen Best Practices zu befolgen, um die Gesamtqualität unserer Codebasis zu verbessern. Dadurch können wir sicherstellen, dass unsere Funktionen nicht nur lesbar und wiederverwendbar, sondern auch langfristig wartbar sind. Dies kann dazu beitragen, die Anzahl von Bugs und Fehlern zu reduzieren, die durch schlecht geschriebenen Code entstehen können, was langfristig Zeit und Ressourcen sparen kann.
Es ist erwähnenswert, dass es bei sauberem Code nicht nur darum geht, Code zu schreiben, der funktioniert; Es geht auch darum, Code zu schreiben, der leicht verstanden, getestet und im Laufe der Zeit geändert werden kann. Daher wird empfohlen, sich die Zeit zu nehmen, die oben beschriebenen Best Practices beim Schreiben von Funktionen sorgfältig zu berücksichtigen, um die Qualität und Wartbarkeit Ihres Codes zu optimieren.

![Was ist überhaupt eine verknüpfte Liste? [Teil 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































