Skip to content

Commit 8b1c5a7

Browse files
authored
Sync changes from the english version (#4)
1 parent a48384e commit 8b1c5a7

File tree

1 file changed

+57
-37
lines changed

1 file changed

+57
-37
lines changed

README.md

+57-37
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# clean-code-typescript [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Clean%20Code%20Typescript&url=https://github.com/mheob/clean-code-typescript)
22

3-
Clean-Code-Konzepte angepasst für TypeScript.
3+
Clean-Code-Konzepte angepasst für TypeScript.
44
Inspiriert von [clean-code-javascript](https://github.com/ryanmcdermott/clean-code-javascript).
55

66
## Inhalt <!-- omit in toc -->
@@ -22,7 +22,7 @@ Inspiriert von [clean-code-javascript](https://github.com/ryanmcdermott/clean-co
2222

2323
![Humorvolles Bild der Software-Qualitätseinschätzung als Zählung, wie viele Schimpfwörter du beim Lesen von Code schreist](https://www.osnews.com/images/comics/wtfm.jpg)
2424

25-
Software-Entwicklungs-Prinzipien, aus Robert C. Martins Buch [_Clean Code_](https://amzn.to/33HgLXZ) (* affiliate link), angepasst für TypeScript. Dies ist kein Style Guide. Es ist ein Leitfaden zur Erstellung von [lesbarer, wiederverwendbarer und refaktorierbarer](https://github.com/ryanmcdermott/3rs-of-software-architecture) Software in TypeScript.
25+
Software-Entwicklungs-Prinzipien, aus Robert C. Martins Buch [_Clean Code_](https://amzn.to/33HgLXZ) (\* affiliate link), angepasst für TypeScript. Dies ist kein Style Guide. Es ist ein Leitfaden zur Erstellung von [lesbarer, wiederverwendbarer und refaktorierbarer](https://github.com/ryanmcdermott/3rs-of-software-architecture) Software in TypeScript.
2626

2727
Nicht jedes Prinzip hierin muss strikt befolgt werden, und noch weniger werden sie allgemein anerkannt sein. Dies hier sind Richtlinien und nichts weiter. Aber sie sind solche, die über viele Jahre kollektiver Erfahrung von den Autoren von _Clean Code_.
2828

@@ -115,9 +115,9 @@ setTimeout(restart, 86400000);
115115

116116
```ts
117117
// Declare them as capitalized named constants.
118-
const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000;
118+
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; // 86400000
119119

120-
setTimeout(restart, MILLISECONDS_IN_A_DAY);
120+
setTimeout(restart, MILLISECONDS_PER_DAY);
121121
```
122122

123123
**[⬆ zum Anfang](#table-of-contents)**
@@ -148,7 +148,7 @@ for (const [id, user] of users) {
148148

149149
### Vermeide Mental Mapping
150150

151-
Explizit ist besser als implizit.
151+
Explizit ist besser als implizit.
152152
_Klarheit ist der König._
153153

154154
**Schlecht:**
@@ -626,6 +626,25 @@ function createMenu(config: MenuConfig) {
626626
createMenu({ body: "Bar" });
627627
```
628628

629+
Oder du kannst den Spread-Operator verwenden:
630+
631+
```ts
632+
function createMenu(config: MenuConfig) {
633+
const menuConfig = {
634+
title: "Foo",
635+
body: "Bar",
636+
buttonText: "Baz",
637+
cancellable: true,
638+
...config,
639+
};
640+
641+
// ...
642+
}
643+
```
644+
645+
Der Spread-Operator und `Object.assign()` sind sich sehr ähnlich.
646+
Der Hauptunterschied besteht darin, dass "Spreading" neue Eigenschaften definiert, während `Object.assign()` sie festlegt. Ausführlicher wird der Unterschied in [diesem Thread erklärt](https://stackoverflow.com/questions/32925460/object-spread-vs-object-assign).
647+
629648
Alternativ kannst du auch eine Destrukturierung mit Standardwerten verwenden:
630649

631650
```ts
@@ -723,16 +742,18 @@ console.log(name);
723742

724743
### Vermeide Nebenwirkungen (Teil 2)
725744

726-
In JavaScript werden Primitive als Wert und Objekte/Arrays als Referenz übergeben. Im Fall von Objekten und Arrays, wenn deine Funktion eine Änderung in einem Warenkorb-Array vornimmt, z.B. indem du einen Artikel zum Kauf hinzufügst, dann wird jede andere Funktion, die dieses `cart`-Array benutzt, von dieser Hinzufügung betroffen sein. Das kann großartig sein, es kann aber auch schlecht sein. Lass uns eine schlechte Situation vorstellen:
745+
Browser und Node.js verarbeiten nur JavaScript, daher muss jeder TypeScript-Code vor dem Ausführen oder Debuggen kompiliert werden. In JavaScript sind einige Werte unveränderlich (immutable) und andere veränderbar (mutable). Objekte und Arrays sind zwei Arten von veränderbaren Werten, daher ist es wichtig, sie sorgfältig zu behandeln, wenn sie als Parameter an eine Funktion übergeben werden. Eine JavaScript-Funktion kann die Eigenschaften eines Objekts oder den Inhalt eines Arrays ändern, was leicht zu Fehlern an anderer Stelle führen kann.
746+
747+
Nehmen wir an, es gibt eine Funktion, die einen Array-Parameter akzeptiert, der einen Warenkorb darstellt. Wenn die Funktion eine Änderung in diesem Warenkorb-Array vornimmt - z. B. indem sie einen Artikel zum Kauf hinzufügt -, dann wird jede andere Funktion, die dasselbe Warenkorb-Array verwendet, von dieser Änderung betroffen sein. Das mag toll sein, kann aber auch schlecht sein. Stellen wir uns eine schlechte Situation vor:
727748

728-
Der Benutzer klickt auf den "Purchase" Button, der eine `purchase` Funktion aufruft, die eine Netzwerkanfrage erzeugt und das `cart` Array an den Server sendet. Aufgrund einer schlechten Netzwerkverbindung muss die Kauffunktion die Anfrage immer wieder neu versuchen. Nun, was ist, wenn der Benutzer in der Zwischenzeit versehentlich auf den "In den Warenkorb"-Button eines Artikels klickt, den er eigentlich nicht will, bevor die Netzwerkanfrage beginnt? Wenn das passiert und die Netzwerkanforderung beginnt, dann wird die Kauffunktion den versehentlich hinzugefügten Artikel senden, weil sie eine Referenz auf ein Warenkorb-Array hat, das die Funktion `addItemToCart` durch das Hinzufügen eines unerwünschten Artikels verändert hat.
749+
Der Benutzer klickt auf den "Purchase" Button, der eine `purchase` Funktion aufruft, die eine Netzwerkanfrage stellt und das `cart` Array an den Server sendet. Aufgrund einer schlechten Netzwerkverbindung muss die Funktion `purchase` die Anfrage immer wieder neu versuchen. Was passiert, wenn der Nutzer in der Zwischenzeit versehentlich auf einen Artikel klickt, den er eigentlich gar nicht haben will, bevor die Netzwerkanfrage gestartet wird? Wenn das passiert und die Netzwerkanfrage beginnt, sendet die `purchase` Funktion den versehentlich hinzugefügten Artikel, weil das Array `cart` geändert wurde.
729750

730-
Eine gute Lösung wäre, dass die Funktion `addItemToCart` immer den `Cart` klont, ihn bearbeitet und den Klon zurückgibt. Dies stellt sicher, dass keine anderen Funktionen, die eine Referenz auf den Warenkorb haben, von den Änderungen betroffen sind.
751+
Eine gute Lösung wäre, wenn die Funktion `addItemToCart` immer `cart` klont, ihn bearbeiten und den Klon zurückgeben würde. Das würde sicherstellen, dass Funktionen, die noch den alten Warenkorb verwenden, nicht von den Änderungen betroffen sind.
731752

732753
Zwei Vorbehalte sind bei diesem Ansatz zu erwähnen:
733754

734755
1. Es kann Fälle geben, in denen du das Eingabeobjekt tatsächlich ändern möchtest, aber wenn du diese Programmierpraxis anwendest, wirst du feststellen, dass diese Fälle ziemlich selten sind. Die meisten Dinge können so refaktorisiert werden, dass sie keine Seiteneffekte haben! (siehe [pure function](https://en.wikipedia.org/wiki/Pure_function))
735-
2. Das Klonen von großen Objekten kann sehr teuer in Bezug auf die Performance sein. Glücklicherweise ist dies in der Praxis kein großes Problem, da es großartige Bibliotheken gibt, die es ermöglichen, dass diese Art von Programmieransatz schnell und nicht so speicherintensiv ist, wie es für dich wäre, wenn du Objekte und Arrays manuell klonen würdest.
756+
2. Das Klonen von großen Objekten kann sehr teuer in Bezug auf die Performance sein. Glücklicherweise ist dies in der Praxis kein großes Problem, da es [großartige Bibliotheken](https://facebook.github.io/immutable-js/) gibt, die es ermöglichen, dass diese Art von Programmieransatz schnell und nicht so speicherintensiv ist, wie es für dich wäre, wenn du Objekte und Arrays manuell klonen würdest.
736757

737758
**Schlecht:**
738759

@@ -1052,7 +1073,7 @@ inventoryTracker("apples", req, "www.inventory-awesome.io");
10521073

10531074
### Verwende Iteratoren und Generatoren
10541075

1055-
Verwende Generatoren und Iterables, wenn du mit Sammlungen von Daten arbeitest, die wie ein Stream verwendet werden.
1076+
Verwende Generatoren und Iterables, wenn du mit Sammlungen von Daten arbeitest, die wie ein Stream verwendet werden.
10561077
Dafür gibt es einige gute Gründe:
10571078

10581079
- entkoppelt den Aufrufer von der Generatorimplementierung in dem Sinne, dass der Aufrufer entscheidet, auf wie viele Items er zugreift
@@ -1238,7 +1259,7 @@ class Circle {
12381259

12391260
### Bevorzuge Unveränderbarkeit
12401261

1241-
TypeScripts Typsystem erlaubt es dir, einzelne Eigenschaften auf einer Schnittstelle/Klasse als _readonly_ zu markieren. Dies erlaubt es dir, auf funktionale Weise zu arbeiten (eine unerwartete Mutation ist schlecht).
1262+
TypeScripts Typsystem erlaubt es dir, einzelne Eigenschaften auf einer Schnittstelle/Klasse als _readonly_ zu markieren. Dies erlaubt es dir, auf funktionale Weise zu arbeiten (eine unerwartete Mutation ist schlecht).
12421263
Für fortgeschrittenere Szenarien gibt es einen eingebauten Typ `Readonly`, der einen Typ `T` nimmt und alle seine Eigenschaften als readonly markiert, indem er gemappte Typen verwendet (siehe [gemappte Typen](https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types)).
12431264

12441265
**Schlecht:**
@@ -1335,8 +1356,8 @@ result.value = 200; // error
13351356

13361357
### `type` vs. `interface`
13371358

1338-
Verwende `type`, wenn du eine Vereinigung oder Kreuzung brauchst. Verwende ein `Interface`, wenn du `extends` oder `implements` brauchst. Es gibt keine strikte Regel, verwende die, die für dich funktioniert.
1339-
Für eine detailliertere Erklärung siehe diese [Antwort](<https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types/54101543#54101543>) über die Unterschiede zwischen `type` und `interface` in TypeScript.
1359+
Verwende `type`, wenn du eine Vereinigung oder Kreuzung brauchst. Verwende ein `Interface`, wenn du `extends` oder `implements` brauchst. Es gibt keine strikte Regel, verwende die, die für dich funktioniert.
1360+
Für eine detailliertere Erklärung siehe diese [Antwort](https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types/54101543#54101543) über die Unterschiede zwischen `type` und `interface` in TypeScript.
13401361

13411362
**Schlecht:**
13421363

@@ -2030,14 +2051,14 @@ DIP wird normalerweise durch die Verwendung eines Inversion of Control (IoC) Con
20302051
**Schlecht:**
20312052

20322053
```ts
2033-
import { readFile as readFileCb } from 'fs';
2034-
import { promisify } from 'util';
2054+
import { readFile as readFileCb } from "fs";
2055+
import { promisify } from "util";
20352056

20362057
const readFile = promisify(readFileCb);
20372058

20382059
type ReportData = {
20392060
// ..
2040-
}
2061+
};
20412062

20422063
class XmlFormatter {
20432064
parse<T>(content: string): T {
@@ -2046,33 +2067,32 @@ class XmlFormatter {
20462067
}
20472068

20482069
class ReportReader {
2049-
20502070
// BAD: We have created a dependency on a specific request implementation.
20512071
// We should just have ReportReader depend on a parse method: `parse`
20522072
private readonly formatter = new XmlFormatter();
20532073

20542074
async read(path: string): Promise<ReportData> {
2055-
const text = await readFile(path, 'UTF8');
2075+
const text = await readFile(path, "UTF8");
20562076
return this.formatter.parse<ReportData>(text);
20572077
}
20582078
}
20592079

20602080
// ...
20612081
const reader = new ReportReader();
2062-
const report = await reader.read('report.xml');
2082+
const report = await reader.read("report.xml");
20632083
```
20642084

20652085
**Gut:**
20662086

20672087
```ts
2068-
import { readFile as readFileCb } from 'fs';
2069-
import { promisify } from 'util';
2088+
import { readFile as readFileCb } from "fs";
2089+
import { promisify } from "util";
20702090

20712091
const readFile = promisify(readFileCb);
20722092

20732093
type ReportData = {
20742094
// ..
2075-
}
2095+
};
20762096

20772097
interface Formatter {
20782098
parse<T>(content: string): T;
@@ -2084,30 +2104,28 @@ class XmlFormatter implements Formatter {
20842104
}
20852105
}
20862106

2087-
20882107
class JsonFormatter implements Formatter {
20892108
parse<T>(content: string): T {
20902109
// Converts a JSON string to an object T
20912110
}
20922111
}
20932112

20942113
class ReportReader {
2095-
constructor(private readonly formatter: Formatter) {
2096-
}
2114+
constructor(private readonly formatter: Formatter) {}
20972115

20982116
async read(path: string): Promise<ReportData> {
2099-
const text = await readFile(path, 'UTF8');
2117+
const text = await readFile(path, "UTF8");
21002118
return this.formatter.parse<ReportData>(text);
21012119
}
21022120
}
21032121

21042122
// ...
21052123
const reader = new ReportReader(new XmlFormatter());
2106-
const report = await reader.read('report.xml');
2124+
const report = await reader.read("report.xml");
21072125

21082126
// or if we had to read a json report
21092127
const reader = new ReportReader(new JsonFormatter());
2110-
const report = await reader.read('report.json');
2128+
const report = await reader.read("report.json");
21112129
```
21122130

21132131
**[⬆ zum Anfang](#table-of-contents)**
@@ -2226,7 +2244,7 @@ describe("Calendar", () => {
22262244

22272245
### Bevorzuge `promises` vor `callbacks`
22282246

2229-
Callbacks sind nicht sauber und verursachen exzessive Mengen an Verschachtlungen _(die Callback-Hölle)_.
2247+
Callbacks sind nicht sauber und verursachen exzessive Mengen an Verschachtlungen _(die Callback-Hölle)_.
22302248
Es gibt Hilfsprogramme, die bestehende Funktionen im Callback-Stil in eine Version umwandeln, die Versprechen zurückgibt (für Node.js siehe [`util.promisify`](https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original), für allgemeine Zwecke siehe [pify](https://www.npmjs.com/package/pify), [es6-promisify](https://www.npmjs.com/package/es6-promisify)).
22312249

22322250
**Schlecht:**
@@ -2362,8 +2380,8 @@ Ausgelöste Fehler sind eine gute Sache! Sie bedeuten, dass die Laufzeitumgebung
23622380

23632381
### Werfe immer Fehler
23642382

2365-
Sowohl JavaScript als auch TypeScript erlauben es dir, ein beliebiges Objekt zu werfen. Ein Promise kann auch mit einem beliebigen Grundobjekt verworfen werden.
2366-
Es ist ratsam, die `throw` Syntax mit einem `Error` Typ zu verwenden. Das liegt daran, dass dein Fehler in höherem Code mit einer `catch` Syntax abgefangen werden könnte. Es wäre sehr verwirrend, dort eine String-Meldung zu fangen und würde das [Debugging schmerzhafter machen](https://basarat.gitbook.io/typescript/type-system/exceptions#always-use-error).
2383+
Sowohl JavaScript als auch TypeScript erlauben es dir, ein beliebiges Objekt zu werfen. Ein Promise kann auch mit einem beliebigen Grundobjekt verworfen werden.
2384+
Es ist ratsam, die `throw` Syntax mit einem `Error` Typ zu verwenden. Das liegt daran, dass dein Fehler in höherem Code mit einer `catch` Syntax abgefangen werden könnte. Es wäre sehr verwirrend, dort eine String-Meldung zu fangen und würde das [Debugging schmerzhafter machen](https://basarat.gitbook.io/typescript/type-system/exceptions#always-use-error).
23672385
Aus dem gleichen Grund solltest du Promises mit `Error` Typen ablehnen.
23682386

23692387
**Schlecht:**
@@ -2397,7 +2415,7 @@ async function get(): Promise<Item[]> {
23972415
```
23982416

23992417
Der Vorteil der Verwendung von `Error` Typen ist, dass sie von der Syntax `try/catch/finally` unterstützt werden und implizit alle Fehler die Eigenschaft `stack` haben, was
2400-
sehr mächtig für das Debugging ist.
2418+
sehr mächtig für das Debugging ist.
24012419
Es gibt auch andere Alternativen, die `throw`-Syntax nicht zu verwenden und stattdessen immer eigene Fehlerobjekte zurückzugeben. TypeScript macht dies noch einfacher. Betrachte das folgende Beispiel:
24022420

24032421
```ts
@@ -2556,7 +2574,7 @@ type Container = {
25562574
};
25572575
```
25582576

2559-
Verwende bevorzugt `PascalCase` für Klassen-, Interface-, Typ- und Namensraumnamen.
2577+
Verwende bevorzugt `PascalCase` für Klassen-, Interface-, Typ- und Namensraumnamen.
25602578
Verwende bevorzugt `camelCase` für Variablen, Funktionen und Klassenmitglieder.
25612579

25622580
**[⬆ zum Anfang](#table-of-contents)**
@@ -2731,7 +2749,7 @@ import { UserService } from "@services/UserService";
27312749

27322750
Die Verwendung eines Kommentars ist ein Hinweis darauf, dass man sich ohne ihn nicht ausdrücken kann. Der Code sollte die einzige Quelle der Wahrheit sein.
27332751

2734-
> Don’t comment bad code—rewrite it.
2752+
> Don’t comment bad code—rewrite it.
27352753
> _Brian W. Kernighan and P. J. Plaugher_
27362754
27372755
### Bevorzuge selbsterklärenden Code anstelle von Kommentaren
@@ -2813,7 +2831,7 @@ function combine(a: number, b: number): number {
28132831

28142832
### Vermeide Positionsmarkierungen
28152833

2816-
Sie fügen normalerweise nur Lärm hinzu. Lass die Funktionen und Variablennamen zusammen mit der richtigen Einrückung und Formatierung deinem Code die visuelle Struktur geben.
2834+
Sie fügen normalerweise nur Lärm hinzu. Lass die Funktionen und Variablennamen zusammen mit der richtigen Einrückung und Formatierung deinem Code die visuelle Struktur geben.
28172835
Die meisten IDEs unterstützen Code-Folding-Features, die es dir ermöglichen, Codeblöcke zu komprimieren/expandieren (siehe Visual Studio Code [folding regions](https://code.visualstudio.com/updates/v1_17#_folding-regions)).
28182836

28192837
**Schlecht:**
@@ -2917,5 +2935,7 @@ Diese Prinzipien sind auch in anderen Sprachen verfügbar:
29172935
- ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [ozanhonamlioglu/clean-code-typescript](https://github.com/ozanhonamlioglu/clean-code-typescript)
29182936
- ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hoangsetup/clean-code-typescript](https://github.com/hoangsetup/clean-code-typescript)
29192937

2920-
Referenzen werden hinzugefügt, sobald die Übersetzungen abgeschlossen sind.
2921-
Schau dir diese [Diskussion](https://github.com/labs42io/clean-code-typescript/issues/15) für weitere Details und Fortschritte an. Du kannst einen unverzichtbaren Beitrag zur _Clean Code_ Community leisten, indem du dies in deine Sprache übersetzst.
2938+
Referenzen werden hinzugefügt, sobald die Übersetzungen abgeschlossen sind.
2939+
Schau dir diese [Diskussion](https://github.com/labs42io/clean-code-typescript/issues/15) für weitere Details und Fortschritte an. Du kannst einen unverzichtbaren Beitrag zur _Clean Code_ Community leisten, indem du dies in deine Sprache übersetzt.
2940+
2941+
**[⬆ zum Anfang](#table-of-contents)**

0 commit comments

Comments
 (0)