From 4503a25d5c91555db4392d7777818df9efc38514 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine OGER Date: Fri, 10 Jan 2020 14:06:03 +0100 Subject: [PATCH 01/24] Add advantage in function parameters --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1e710a99..258eb49a 100644 --- a/README.md +++ b/README.md @@ -251,11 +251,12 @@ destructuring syntax. This has a few advantages: 1. When someone looks at the function signature, it's immediately clear what properties are being used. -2. Destructuring also clones the specified primitive values of the argument +2. It can be used to simulate named parameters. +3. Destructuring also clones the specified primitive values of the argument object passed into the function. This can help prevent side effects. Note: objects and arrays that are destructured from the argument object are NOT cloned. -3. Linters can warn you about unused properties, which would be impossible +4. Linters can warn you about unused properties, which would be impossible without destructuring. **Bad:** @@ -264,6 +265,9 @@ destructuring syntax. This has a few advantages: function createMenu(title, body, buttonText, cancellable) { // ... } + +createMenu("Foo", "Bar", "Baz", true); + ``` **Good:** From 8491866a87641708ee4253a1b89b5d8a0243d426 Mon Sep 17 00:00:00 2001 From: Bimochan Shrestha Date: Tue, 21 Jan 2020 14:13:48 +0545 Subject: [PATCH 02/24] Change argument name from inner variable name --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 950f1d20..1a03e71a 100644 --- a/README.md +++ b/README.md @@ -543,7 +543,7 @@ const menuConfig = { }; function createMenu(config) { - config = Object.assign( + let finalConfig = Object.assign( { title: "Foo", body: "Bar", @@ -552,7 +552,7 @@ function createMenu(config) { }, config ); - + return finalConfig // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } From ba9797eb939b0f5edad0b19babc904f697bced58 Mon Sep 17 00:00:00 2001 From: Justin Lee Date: Tue, 21 Jan 2020 13:17:12 -0800 Subject: [PATCH 03/24] Update README.md Small grammar correction. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 950f1d20..08a33104 100644 --- a/README.md +++ b/README.md @@ -291,7 +291,7 @@ createMenu({ This is by far the most important rule in software engineering. When functions do more than one thing, they are harder to compose, test, and reason about. -When you can isolate a function to just one action, they can be refactored +When you can isolate a function to just one action, it can be refactored easily and your code will read much cleaner. If you take nothing else away from this guide other than this, you'll be ahead of many developers. From 0ab8ebaed48ac72c4f27680f7c680dc7e6cf407d Mon Sep 17 00:00:00 2001 From: Justin Lee Date: Tue, 21 Jan 2020 13:20:28 -0800 Subject: [PATCH 04/24] Update README.md Small grammar correction --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 950f1d20..c7f7459b 100644 --- a/README.md +++ b/README.md @@ -650,7 +650,7 @@ then any other function that uses that `cart` array will be affected by this addition. That may be great, however it can be bad too. Let's imagine a bad situation: -The user clicks the "Purchase", button which calls a `purchase` function that +The user clicks the "Purchase" button which calls a `purchase` function that spawns a network request and sends the `cart` array to the server. Because of a bad network connection, the `purchase` function has to keep retrying the request. Now, what if in the meantime the user accidentally clicks "Add to Cart" From c18b9766f4330f301d8fb68de8f38286f1c42cef Mon Sep 17 00:00:00 2001 From: Raigo Jerva Date: Wed, 22 Jan 2020 00:19:37 +0000 Subject: [PATCH 05/24] sort translations --- README.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 08a33104..0aac9ff5 100644 --- a/README.md +++ b/README.md @@ -2355,28 +2355,24 @@ const actions = function() { This is also available in other languages: -- ![fr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/France.png) **French**: - [GavBaros/clean-code-javascript-fr](https://github.com/GavBaros/clean-code-javascript-fr) +- ![bd](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bangladesh.png) **Bangla(বাংলা)**: [InsomniacSabbir/clean-code-javascript/](https://github.com/InsomniacSabbir/clean-code-javascript/) - ![br](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Brazil.png) **Brazilian Portuguese**: [fesnt/clean-code-javascript](https://github.com/fesnt/clean-code-javascript) -- ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Uruguay.png) **Spanish**: [andersontr15/clean-code-javascript](https://github.com/andersontr15/clean-code-javascript-es) -- ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [tureey/clean-code-javascript](https://github.com/tureey/clean-code-javascript) - ![cn](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/China.png) **Simplified Chinese**: - [alivebao/clean-code-js](https://github.com/alivebao/clean-code-js) - [beginor/clean-code-javascript](https://github.com/beginor/clean-code-javascript) - ![tw](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Taiwan.png) **Traditional Chinese**: [AllJointTW/clean-code-javascript](https://github.com/AllJointTW/clean-code-javascript) +- ![fr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/France.png) **French**: [GavBaros/clean-code-javascript-fr](https://github.com/GavBaros/clean-code-javascript-fr) - ![de](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Germany.png) **German**: [marcbruederlin/clean-code-javascript](https://github.com/marcbruederlin/clean-code-javascript) +- ![id](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Indonesia.png) **Indonesia**: [andirkh/clean-code-javascript/](https://github.com/andirkh/clean-code-javascript/) +- ![it](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Italy.png) **Italian**: [frappacchio/clean-code-javascript/](https://github.com/frappacchio/clean-code-javascript/) +- ![ja](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Japan.png) **Japanese**: [mitsuruog/clean-code-javascript/](https://github.com/mitsuruog/clean-code-javascript/) - ![kr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/South-Korea.png) **Korean**: [qkraudghgh/clean-code-javascript-ko](https://github.com/qkraudghgh/clean-code-javascript-ko) - ![pl](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Poland.png) **Polish**: [greg-dev/clean-code-javascript-pl](https://github.com/greg-dev/clean-code-javascript-pl) - ![ru](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Russia.png) **Russian**: - [BoryaMogila/clean-code-javascript-ru/](https://github.com/BoryaMogila/clean-code-javascript-ru/) - [maksugr/clean-code-javascript](https://github.com/maksugr/clean-code-javascript) +- ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [tureey/clean-code-javascript](https://github.com/tureey/clean-code-javascript) +- ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Uruguay.png) **Spanish**: [andersontr15/clean-code-javascript](https://github.com/andersontr15/clean-code-javascript-es) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) -- ![ja](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Japan.png) **Japanese**: [mitsuruog/clean-code-javascript/](https://github.com/mitsuruog/clean-code-javascript/) -- ![id](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Indonesia.png) **Indonesia**: - [andirkh/clean-code-javascript/](https://github.com/andirkh/clean-code-javascript/) -- ![it](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Italy.png) **Italian**: - [frappacchio/clean-code-javascript/](https://github.com/frappacchio/clean-code-javascript/) -- ![bd](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bangladesh.png) **Bangla(বাংলা)**: - [InsomniacSabbir/clean-code-javascript/](https://github.com/InsomniacSabbir/clean-code-javascript/) - + **[⬆ back to top](#table-of-contents)** From a812aa93c8e7eeca7bfa27e930244987644a5a90 Mon Sep 17 00:00:00 2001 From: Raigo Jerva Date: Wed, 22 Jan 2020 00:20:22 +0000 Subject: [PATCH 06/24] add armenian translation to the list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0aac9ff5..514956db 100644 --- a/README.md +++ b/README.md @@ -2355,6 +2355,7 @@ const actions = function() { This is also available in other languages: +- ![am](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Armenia.png) **Armenian**: [hanumanum/clean-code-javascript/](https://github.com/hanumanum/clean-code-javascript) - ![bd](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bangladesh.png) **Bangla(বাংলা)**: [InsomniacSabbir/clean-code-javascript/](https://github.com/InsomniacSabbir/clean-code-javascript/) - ![br](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Brazil.png) **Brazilian Portuguese**: [fesnt/clean-code-javascript](https://github.com/fesnt/clean-code-javascript) - ![cn](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/China.png) **Simplified Chinese**: From 5f8daa0121e4dfab1eb0d685226e669da0984e50 Mon Sep 17 00:00:00 2001 From: Risto McIntosh Date: Thu, 6 Feb 2020 21:44:02 -0600 Subject: [PATCH 07/24] Fixed a small typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 514956db..db2a4a25 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ saveCityZipCode( ```javascript const address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/; -const [, city, zipCode] = address.match(cityZipCodeRegex) || []; +const [city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode); ``` From c90b109b38fe6174c68f0c30d02b1b32149a5371 Mon Sep 17 00:00:00 2001 From: Risto McIntosh Date: Fri, 7 Feb 2020 08:12:47 -0600 Subject: [PATCH 08/24] Add an underscore to "Use explanatory variables" This makes the destructuring a little more readable --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db2a4a25..02c46fde 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ saveCityZipCode( ```javascript const address = "One Infinite Loop, Cupertino 95014"; const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/; -const [city, zipCode] = address.match(cityZipCodeRegex) || []; +const [_, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode); ``` From 2edfeef74002f7aeaa15a7bea4adb047b85dd539 Mon Sep 17 00:00:00 2001 From: Burak Sonmez Date: Thu, 26 Mar 2020 08:35:58 +0300 Subject: [PATCH 09/24] turkish added --- README.md | 901 +++++++++++++++++++++--------------------------------- 1 file changed, 355 insertions(+), 546 deletions(-) diff --git a/README.md b/README.md index bbe7a083..d7747ff9 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,55 @@ # clean-code-javascript -## Table of Contents +## İçindekiler -1. [Introduction](#introduction) -2. [Variables](#variables) -3. [Functions](#functions) -4. [Objects and Data Structures](#objects-and-data-structures) -5. [Classes](#classes) +1. [Giriş](#Giriş) +2. [Değişkenler](#Değişkenler) +3. [Fonksiyonlar](#Fonksiyonlar) +4. [Nesneler ve Veri Yapıları](#nesneler-ve-veri-yapıları) +5. [Sınıflar (Class)](#sınıflar) 6. [SOLID](#solid) -7. [Testing](#testing) -8. [Concurrency](#concurrency) -9. [Error Handling](#error-handling) -10. [Formatting](#formatting) -11. [Comments](#comments) -12. [Translation](#translation) +7. [Testler](#testler) +8. [Tutarlılık](#Tutarlılık) +9. [Hata Yönetimi](#Hata-Yönetimi) +10. [Biçimlendirme](#Biçimlendirme) +11. [Yorumlar](#yorumlar) +12. [Çeviriler](#çeviriler) -## Introduction +## Giriş -![Humorous image of software quality estimation as a count of how many expletives -you shout when reading code](https://www.osnews.com/images/comics/wtfm.jpg) +![Kod okurken kaç defa bağıracağınızın bir sayısı olarak yazılım kalite tahmininin görüntüsü](https://www.osnews.com/images/comics/wtfm.jpg) -Software engineering principles, from Robert C. Martin's book -[_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882), -adapted for JavaScript. This is not a style guide. It's a guide to producing -[readable, reusable, and refactorable](https://github.com/ryanmcdermott/3rs-of-software-architecture) software in JavaScript. +Robert C. Martin'nın kitabı olan ve yazılım mühendisliği ilkerini barındıran [_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)'un JavaScript için uyarlanmış hali. Bu bir tarz rehberi değil. JavaScript'te [okunabilir, yeniden kullanılabilir ve yeniden düzenlenebilir](https://github.com/ryanmcdermott/3rs-of-software-architecture) yazılımlar üretmeye yönelik bir kılavuzdur. -Not every principle herein has to be strictly followed, and even fewer will be -universally agreed upon. These are guidelines and nothing more, but they are -ones codified over many years of collective experience by the authors of -_Clean Code_. +Buradaki her ilkeye kesinlikle uyulmak zorunda değildir ve daha azı evrensel olarak kabul edilecektir. Bunlar önerilerden başka bir şey değildir, fakat bunlar _Clean Code_ yazarları tarafından uzun yıllar süren tecrübeler ile kodlandı. -Our craft of software engineering is just a bit over 50 years old, and we are -still learning a lot. When software architecture is as old as architecture -itself, maybe then we will have harder rules to follow. For now, let these -guidelines serve as a touchstone by which to assess the quality of the -JavaScript code that you and your team produce. +Yazılım mühendisliği zanaatımız 50 yaşın biraz üzerinde ve hala çok şey öğreniyoruz. Yazılım mimarisi, mimarinin kendisi kadar eski olduğunda, belki de takip edilmesi daha zor kurallarımız olacak. Şimdi, bu önerilerin sizin ve ekibinizin ürettiği JavaScript kodunun kalitesini değerlendirmek için bir mihenk taşı işlevi görmesine izin verin. -One more thing: knowing these won't immediately make you a better software -developer, and working with them for many years doesn't mean you won't make -mistakes. Every piece of code starts as a first draft, like wet clay getting -shaped into its final form. Finally, we chisel away the imperfections when -we review it with our peers. Don't beat yourself up for first drafts that need -improvement. Beat up the code instead! +Bir şey daha: bunların bilinmesi sizi hemen daha iyi bir yazılım geliştiricisi yapmaz ve uzun yıllar onlarla çalışmak hata yapmayacağınız anlamına gelmez. -## **Variables** +Her kod parçası ilk taslak olarak başlar, örneğin ıslak kil son halini alır. Son olarak, akranlarımızla gözden geçirdiğimizde kusurları kesiyoruz. İyileştirilmesi gereken ilk taslaklar için kendinize yüklenmeyin. Onun yerine kodunuza yüklenin. -### Use meaningful and pronounceable variable names +## **Değişkenler** -**Bad:** +### Anlamlı ve belirgin değişken adları kullanın + +**Kötü:** ```javascript const yyyymmdstr = moment().format("YYYY/MM/DD"); ``` -**Good:** +**İyi:** ```javascript const currentDate = moment().format("YYYY/MM/DD"); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use the same vocabulary for the same type of variable +### Aynı değişken türü için aynı kelimeleri kullanın -**Bad:** +**Kötü:** ```javascript getUserInfo(); @@ -71,45 +57,41 @@ getClientData(); getCustomerRecord(); ``` -**Good:** +**İyi:** ```javascript getUser(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use searchable names +### Aranabilir isimler kullanın -We will read more code than we will ever write. It's important that the code we -do write is readable and searchable. By _not_ naming variables that end up -being meaningful for understanding our program, we hurt our readers. -Make your names searchable. Tools like -[buddy.js](https://github.com/danielstjules/buddy.js) and -[ESLint](https://github.com/eslint/eslint/blob/660e0918933e6e7fede26bc675a0763a6b357c94/docs/rules/no-magic-numbers.md) -can help identify unnamed constants. +Yazacağımızdan daha fazla kod okuyacağız. Yazdığımız kodun okunabilir ve aranabilir olması önemlidir. Değişkenleri anlamlı ve anlaşılabilir _isimlendirmemekle_, okuyucuya zarar veriyoruz. +Adlarınızı aranabilir hale getirin. [buddy.js](https://github.com/danielstjules/buddy.js) ve +[ESLint](https://github.com/eslint/eslint/blob/660e0918933e6e7fede26bc675a0763a6b357c94/docs/rules/no-magic-numbers.md) gibi araçlar isimlendirilmemiş sabitlerinizi belirlemenize yardımcı olacaktır. -**Bad:** +**Kötü:** ```javascript -// What the heck is 86400000 for? +// 86400000 neydi ? setTimeout(blastOff, 86400000); ``` -**Good:** +**İyi:** ```javascript -// Declare them as capitalized named constants. +// Bunları büyük harfle adlandırılmış sabitler olarak bildirin. const MILLISECONDS_IN_A_DAY = 86_400_000; setTimeout(blastOff, MILLISECONDS_IN_A_DAY); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use explanatory variables +### Açıklayıcı değişkenler kullan -**Bad:** +**Kötü:** ```javascript const address = "One Infinite Loop, Cupertino 95014"; @@ -120,7 +102,7 @@ saveCityZipCode( ); ``` -**Good:** +**İyi:** ```javascript const address = "One Infinite Loop, Cupertino 95014"; @@ -129,13 +111,13 @@ const [_, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid Mental Mapping +### Kafadan planmaktan kaçının -Explicit is better than implicit. +Açık olmak, ima etmekten iyidir. -**Bad:** +**Kötü:** ```javascript const locations = ["Austin", "New York", "San Francisco"]; @@ -145,12 +127,12 @@ locations.forEach(l => { // ... // ... // ... - // Wait, what is `l` for again? + // Bir dakika, 'l' neydi? dispatch(l); }); ``` -**Good:** +**İyi:** ```javascript const locations = ["Austin", "New York", "San Francisco"]; @@ -164,14 +146,13 @@ locations.forEach(location => { }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Don't add unneeded context +### Gereksiz içerikler eklemeyin -If your class/object name tells you something, don't repeat that in your -variable name. +Sınıf / nesne adınız size bir şey söylüyorsa, bunu değişken adınızda tekrarlamayın. -**Bad:** +**Kötü:** ```javascript const Car = { @@ -185,7 +166,7 @@ function paintCar(car) { } ``` -**Good:** +**İyi:** ```javascript const Car = { @@ -199,16 +180,13 @@ function paintCar(car) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use default arguments instead of short circuiting or conditionals +### Kısa devre veya şartlar yerine önceden tanımlanmış argümanlar kullanın -Default arguments are often cleaner than short circuiting. Be aware that if you -use them, your function will only provide default values for `undefined` -arguments. Other "falsy" values such as `''`, `""`, `false`, `null`, `0`, and -`NaN`, will not be replaced by a default value. +Önceden tanımlanan argümanlar genellikle kısa devrelere göre daha temizdir. Bunları kullanırsanız şunun farkında olun, fonksiyonunuz sadece `tanımsız` _(undefined)_ değerler için önceden tanımlanmış argümana kullanacaktır. `''`, `""`, `false`, `null`, `0`, ve `NaN` gibi "yanlış denilebilecek" değerler önceden tanımlanmış bir değerle değiştirilmez. -**Bad:** +**Kötü:** ```javascript function createMicrobrewery(name) { @@ -217,7 +195,7 @@ function createMicrobrewery(name) { } ``` -**Good:** +**İyi:** ```javascript function createMicrobrewery(name = "Hipster Brew Co.") { @@ -225,41 +203,27 @@ function createMicrobrewery(name = "Hipster Brew Co.") { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Functions** +## **Fonksiyonlar** -### Function arguments (2 or fewer ideally) +### Fonksiyonlar argümanları (Tercihen 2 veya daha az) -Limiting the amount of function parameters is incredibly important because it -makes testing your function easier. Having more than three leads to a -combinatorial explosion where you have to test tons of different cases with -each separate argument. +Fonksiyon parametrelerinin sayısını sınırlamak inanılmaz derecede önemlidir, çünkü fonksiyonunuzu test etmeyi kolaylaştırır. Üçten fazlasına sahip olmak, her bir argümanla tonlarca farklı vakayı test etmeniz gereken bir kombinasyonel patlamaya yol açar. -One or two arguments is the ideal case, and three should be avoided if possible. -Anything more than that should be consolidated. Usually, if you have -more than two arguments then your function is trying to do too much. In cases -where it's not, most of the time a higher-level object will suffice as an -argument. +Bir veya iki argüman ideal durumdur ve mümkünse üç tanesinden kaçınılmalıdır. Bundan daha fazlası birleştirilmeldir. Genellikle, +ikiden fazla argüman sonra fonksiyonunuz çok işlem yapmaya çalışıyor. Olmadığı durumlarda, çoğu zaman daha üst düzey bir nesne argüman olarak yeterli olacaktır. -Since JavaScript allows you to make objects on the fly, without a lot of class -boilerplate, you can use an object if you are finding yourself needing a -lot of arguments. +JavaScript havada nesne yapmanıza olanak sağladığı için, bir çok sınıf yapısına gerek kalmadan, bir nesneyi birden fazla nesne kullanmadan kullanabilirsiniz. -To make it obvious what properties the function expects, you can use the ES2015/ES6 -destructuring syntax. This has a few advantages: +Fonksiyonun hangi özellikleri beklediğini netleştirmek için ES2015 / ES6 ayrıştırma sintaksını kullanabilirsiniz. Bunun birkaç avantajı vardır: -1. When someone looks at the function signature, it's immediately clear what - properties are being used. -2. It can be used to simulate named parameters. -3. Destructuring also clones the specified primitive values of the argument - object passed into the function. This can help prevent side effects. Note: - objects and arrays that are destructured from the argument object are NOT - cloned. -4. Linters can warn you about unused properties, which would be impossible - without destructuring. +1. Birisi fonksiyonun imzasına baktığında, hangi özelliklerin kullanıldığını hemen anlar.. +2. Adlandırılmış parametreleri simüle etmek için kullanılabilir. +3. Ayrıştırma işlemi ayrıca fonksiyona iletilen argüman nesnesinin belirtilen ilk değerlerini de klonlar. Bu, yan etkilerin önlenmesine yardımcı olabilir. Not: Argüman nesnelerinden ayrıştırılan nesneler ve diziler klonlanmaz! +4. Linters, sizi kullanılmayan değerler için uyarabilir bu da ayrıştırmadan imkansız olurdu. -**Bad:** +**Kötü:** ```javascript function createMenu(title, body, buttonText, cancellable) { @@ -270,7 +234,7 @@ createMenu("Foo", "Bar", "Baz", true); ``` -**Good:** +**İyi:** ```javascript function createMenu({ title, body, buttonText, cancellable }) { @@ -285,17 +249,13 @@ createMenu({ }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Functions should do one thing +### Fonksiyonlar bir şey yapmalı -This is by far the most important rule in software engineering. When functions -do more than one thing, they are harder to compose, test, and reason about. -When you can isolate a function to just one action, it can be refactored -easily and your code will read much cleaner. If you take nothing else away from -this guide other than this, you'll be ahead of many developers. +Bu, yazılım mühendisliğinde açık ara en önemli kuraldır. Fonksiyonlar birden fazla şey yaptığında, birleştirmesi, test etmesi ve anlamdırılması daha zordur. Bir fonksiyonu yalnızca bir eyleme ayırabildiğinizde, kolayca yeniden düzenlenebilir ve kodunuz çok daha temiz okunur. Bu yazıdan başka bir şey almazsanız dahi sadece bununla birçok geliştiricinin önünde olacaksınız. -**Bad:** +**Kötü:** ```javascript function emailClients(clients) { @@ -308,7 +268,7 @@ function emailClients(clients) { } ``` -**Good:** +**İyi:** ```javascript function emailActiveClients(clients) { @@ -321,11 +281,11 @@ function isActiveClient(client) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Function names should say what they do +### Fonksiyon isimleri ne yaptıklarını anlatmalı -**Bad:** +**Kötü:** ```javascript function addToDate(date, month) { @@ -334,11 +294,11 @@ function addToDate(date, month) { const date = new Date(); -// It's hard to tell from the function name what is added +// Fonksiyonun adından ne eklendiğini söylemek zor addToDate(date, 1); ``` -**Good:** +**İyi:** ```javascript function addMonthToDate(month, date) { @@ -349,15 +309,13 @@ const date = new Date(); addMonthToDate(1, date); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Functions should only be one level of abstraction +### Fonksiyonlar soyutlaştırmadan sadece bir seviye uzak olmalıdır -When you have more than one level of abstraction your function is usually -doing too much. Splitting up functions leads to reusability and easier -testing. +Birden fazla soyutlama seviyeniz olduğunda fonksiyonunuz genellikle çok fazla şey yapar. Fonksiyonların bölünmesi, yeniden kullanılabilirliği ve daha kolay test yapılmasını sağlayacak. -**Bad:** +**Kötü:** ```javascript function parseBetterJSAlternative(code) { @@ -384,7 +342,7 @@ function parseBetterJSAlternative(code) { } ``` -**Good:** +**İyi:** ```javascript function parseBetterJSAlternative(code) { @@ -421,32 +379,19 @@ function parse(tokens) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Remove duplicate code +### Tekrarlanan kodu sil -Do your absolute best to avoid duplicate code. Duplicate code is bad because it -means that there's more than one place to alter something if you need to change -some logic. +Tekrarlanan kodlardan kaçınmak için elinizden geleni yapın. Tekrarlanan kod kötü çünkü bazı mantığı değiştirmeniz gerekirse bir şeyi değiştirmek için birden fazla yer olduğu anlamına geliyor. -Imagine if you run a restaurant and you keep track of your inventory: all your -tomatoes, onions, garlic, spices, etc. If you have multiple lists that -you keep this on, then all have to be updated when you serve a dish with -tomatoes in them. If you only have one list, there's only one place to update! +Bir restoran işlettiğinizi ve stoklarınızı takip ettiğinizi düşünün: tüm domates, soğan, sarımsak, baharat, vb. onlara. Yalnızca bir listeniz varsa, güncellenecek tek bir yer vardır! -Oftentimes you have duplicate code because you have two or more slightly -different things, that share a lot in common, but their differences force you -to have two or more separate functions that do much of the same things. Removing -duplicate code means creating an abstraction that can handle this set of -different things with just one function/module/class. +Çoğunlukla yinelenen kodunuz vardır, çünkü çoğu şeyi ortak paylaşsalar dahi çok küçük bir kaç farklılık vardır, ancak farklılıkları sizi aynı şeylerin çoğunu yapan iki veya daha fazla ayrı fonksiyona sahip olmaya zorlar. Tekrarlanan kodun kaldırılması, bu farklı şeyleri tek bir fonksiyon / modül / sınıfla işleyebilecek bir soyutlama oluşturmak anlamına gelir. -Getting the abstraction right is critical, that's why you should follow the -SOLID principles laid out in the _Classes_ section. Bad abstractions can be -worse than duplicate code, so be careful! Having said this, if you can make -a good abstraction, do it! Don't repeat yourself, otherwise you'll find yourself -updating multiple places anytime you want to change one thing. +Soyutlamayı doğru yapmak kritik öneme sahiptir, bu yüzden _Sınıflar_ bölümünde belirtilen SOLID ilkelerini izlemelisiniz. Kötü soyutlamalar yinelenen koddan daha kötü olabilir, bu yüzden dikkatli olun! Bunu söyledikten sonra, eğer iyi bir soyutlama yapabilirseniz, yapın! Kendinizi tekrarlamayın, aksi takdirde bir şeyi değiştirmek istediğinizde kendinizi birden fazla yeri güncellerken bulacaksınız. -**Bad:** +**Kötü:** ```javascript function showDeveloperList(developers) { @@ -480,7 +425,7 @@ function showManagerList(managers) { } ``` -**Good:** +**İyi:** ```javascript function showEmployeeList(employees) { @@ -507,11 +452,11 @@ function showEmployeeList(employees) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Set default objects with Object.assign +### Object.assign ile varsayılan nesneleri ayarlama -**Bad:** +**Kötü:** ```javascript const menuConfig = { @@ -532,12 +477,12 @@ function createMenu(config) { createMenu(menuConfig); ``` -**Good:** +**İyi:** ```javascript const menuConfig = { title: "Order", - // User did not include 'body' key + // Kullanıcı 'body' eklemedi buttonText: "Send", cancellable: true }; @@ -553,20 +498,20 @@ function createMenu(config) { config ); - // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} + // config çıktısı şimdi : {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } createMenu(menuConfig); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Don't use flags as function parameters +### Fonksiyon parametrelerinde işaretleme kullanma -Flags tell your user that this function does more than one thing. Functions should do one thing. Split out your functions if they are following different code paths based on a boolean. +İşaretlemeler fonksiyonunuzun birden fazla şey yaptığını gösterir. Fonkisyonlar sadece tek şey yapmalılar. Eğer aşağıdakine benzer değişiklere ve mantıksal operatorlere sahip fonksiyonunuz varsa fonksiyonlarınızı ayırın. -**Bad:** +**Kötü:** ```javascript function createFile(name, temp) { @@ -578,7 +523,7 @@ function createFile(name, temp) { } ``` -**Good:** +**İyi:** ```javascript function createFile(name) { @@ -590,30 +535,21 @@ function createTempFile(name) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid Side Effects (part 1) +### Yan Etkilerden Kaçının (Bölüm 1) -A function produces a side effect if it does anything other than take a value in -and return another value or values. A side effect could be writing to a file, -modifying some global variable, or accidentally wiring all your money to a -stranger. +Bir fonksiyon, bir değeri alıp başka bir değer veya değer döndürmekten başka bir şey yaparsa yan etki üretir. Bir yan etki, bir dosyaya yazma, bazı global değişkeni değiştirme veya yanlışlıkla tüm paranızı bir yabancıya gönderme olabilir. -Now, you do need to have side effects in a program on occasion. Like the previous -example, you might need to write to a file. What you want to do is to -centralize where you are doing this. Don't have several functions and classes -that write to a particular file. Have one service that does it. One and only one. +Şimdi, zaman zaman bir programda yan etkilere sahip olmanız gerekir. Önceki örnekte olduğu gibi, bir dosyaya yazmanız gerekebilir. Yapmak istediğiniz, bunu yapacağınız yeri merkezileştirmektir. Birden fazla yazma işlemi yapan fonksiyonlar veya sınıflar yapmayın. Bunu yapan bir servisiniz olsun. Bir ve sadece bir. -The main point is to avoid common pitfalls like sharing state between objects -without any structure, using mutable data types that can be written to by anything, -and not centralizing where your side effects occur. If you can do this, you will -be happier than the vast majority of other programmers. +Buradaki ana nokta, herhangi bir yapıya sahip olmayan nesneler arasında durumu(state) paylaşmak, herhangi bir şeyle yazılabilen değiştirilebilir(mutable) veri türlerini kullanmak ve yan etkilerinizin nerede ortaya çıktığını merkezileştirmemek gibi yaygın tuzaklardan kaçınmaktır. Bunu yapabilirseniz, diğer programcıların büyük çoğunluğundan daha mutlu olacaksınız. -**Bad:** +**Kötü:** ```javascript -// Global variable referenced by following function. -// If we had another function that used this name, now it'd be an array and it could break it. +// Aşağıdaki fonksiyon Global değişkeni refere alıyor +// Bu adı kullanan başka bir fonksiyonumuz olsaydı, şimdi bir dizi olurdu ve onu bozacaktı. let name = "Ryan McDermott"; function splitIntoFirstAndLastName() { @@ -625,7 +561,7 @@ splitIntoFirstAndLastName(); console.log(name); // ['Ryan', 'McDermott']; ``` -**Good:** +**İyi:** ```javascript function splitIntoFirstAndLastName(name) { @@ -639,44 +575,27 @@ console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott']; ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid Side Effects (part 2) +### Yan Etkilerden Kaçının (Bölüm 2) -In JavaScript, primitives are passed by value and objects/arrays are passed by -reference. In the case of objects and arrays, if your function makes a change -in a shopping cart array, for example, by adding an item to purchase, -then any other function that uses that `cart` array will be affected by this -addition. That may be great, however it can be bad too. Let's imagine a bad -situation: +JavaScript'te, temel öğeler değerlerle aktarılır (passed by value) ve objeler/diziler referans ile aktarılır (passed by reference). -The user clicks the "Purchase" button which calls a `purchase` function that -spawns a network request and sends the `cart` array to the server. Because -of a bad network connection, the `purchase` function has to keep retrying the -request. Now, what if in the meantime the user accidentally clicks "Add to Cart" -button on an item they don't actually want before the network request begins? -If that happens and the network request begins, then that purchase function -will send the accidentally added item because it has a reference to a shopping -cart array that the `addItemToCart` function modified by adding an unwanted -item. +Bu durumda, nesnelerde ve dizilerde fonksiyonunuz bir değişiklik yaparsa +örneğin, bir alışveriş sepeti dizisinde, satın almak için bir öğe ekleyerek, +bu `cart` dizisini kullanan diğer fonksiyonlar bu eklemeden etkilenecektir. +Bu harika olabilir, ancak kötü de olabilir. Kötü bir hayal edelim +durum: -A great solution would be for the `addItemToCart` to always clone the `cart`, -edit it, and return the clone. This ensures that no other functions that are -holding onto a reference of the shopping cart will be affected by any changes. +Kullanıcı, 'Satın Al' butonuna basar ve bu `satınal` fonksiyonu sunucuya bir istek atarak `sepet` dizisini sunucuya gönderir. Kötü bir ağ bağlantısı nedeniyle, `satınal` işlevi isteği yeniden denemeye devam etmelidir. Şimdi, bu arada kullanıcı yanlışlıkla ağ isteği başlamadan istemedikleri bir öğenin üzerine "Sepete Ekle" düğmesini tıklarsa ne olur? Bu olursa ve ağ isteği başlarsa, yanlışlıkla satın alınan öğeyi gönderir çünkü alışveriş sepeti dizisine, `ürünüSepeteEkle` işlevinin istenmeyen bir öğe ekleyerek değiştirdiği bir referansı vardır. `ürünüSepeteEkle` ın her zaman `sepeti` klonlaması, düzenlemesi ve klonu döndürmesi için harika bir çözüm olacaktır. Bu, alışveriş sepetinin referansını tutan başka hiçbir işlevin herhangi bir değişiklikten etkilenmemesini sağlar. -Two caveats to mention to this approach: +Bu yaklaşıma değinecek iki uyarı: -1. There might be cases where you actually want to modify the input object, - but when you adopt this programming practice you will find that those cases - are pretty rare. Most things can be refactored to have no side effects! +1. Girilen nesnesini gerçekten değiştirmek istediğiniz durumlar olabilir, ancak bunu uyguladığınızda, bu vakaların oldukça nadir olduğunu göreceksiniz. Çoğu şeyin yan etkisi olmayacak şekilde yeniden düzenlenebilir! -2. Cloning big objects can be very expensive in terms of performance. Luckily, - this isn't a big issue in practice because there are - [great libraries](https://facebook.github.io/immutable-js/) that allow - this kind of programming approach to be fast and not as memory intensive as - it would be for you to manually clone objects and arrays. +2. Büyük nesneleri klonlamak performans açısından çok pahalı olabilir. Neyse ki, bu pratikte büyük bir sorun değildir, çünkü bu tür programlama yaklaşımlarını manuel yapmaktansa daha hızlı olmasını ve büyük nesneleri ve dizileri klonlanlarken daha az bellek harcayan [harika kütüphaneler](https://facebook.github.io/immutable-js/) vardır. -**Bad:** +**Kötü:** ```javascript const addItemToCart = (cart, item) => { @@ -684,7 +603,7 @@ const addItemToCart = (cart, item) => { }; ``` -**Good:** +**İyi:** ```javascript const addItemToCart = (cart, item) => { @@ -692,21 +611,17 @@ const addItemToCart = (cart, item) => { }; ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** + +### Global fonksiyonlar yazma -### Don't write to global functions +Globalleri kirletmek JavaScript'te kötü bir uygulamadır, çünkü başka bir kütüphaneyle çakıştırabilirsiniz ve API'lerinizi kullananlar kişiler canlıya çıkana kadar bu aksi durumların farkında olmayabilir. -Polluting globals is a bad practice in JavaScript because you could clash with another -library and the user of your API would be none-the-wiser until they get an -exception in production. Let's think about an example: what if you wanted to -extend JavaScript's native Array method to have a `diff` method that could -show the difference between two arrays? You could write your new function -to the `Array.prototype`, but it could clash with another library that tried -to do the same thing. What if that other library was just using `diff` to find -the difference between the first and last elements of an array? This is why it -would be much better to just use ES2015/ES6 classes and simply extend the `Array` global. +Bir örnek düşünelim: JavaScript'in yerel kütüphanesindeki dizi `diff` methodunu genişletmek ve iki dizinin farklılıklarını göstermek istediğinizi var sayalım. JavaScript'in yerel Array yöntemini iki dizi arasındaki farkı gösterebilecek bir "diff" yöntemine genişletmek mi istiyorsunuz? -**Bad:** +Yeni fonksiyonunuzu `Array.prototype`'e yazabilirsiniz, ancak aynı şeyi yapmaya çalışan başka bir kütüphane ile çakışabilir. Ya diğer kütüphane bir dizinin ilk ve son elemanları arasındaki farkı bulmak için sadece `diff` kullanıyorsa? Bu yüzden sadece ES2015 / ES6 sınıflarını kullanmak ve `Array` globalini genişletmek çok daha iyi olurdu. + +**Kötü:** ```javascript Array.prototype.diff = function diff(comparisonArray) { @@ -715,7 +630,7 @@ Array.prototype.diff = function diff(comparisonArray) { }; ``` -**Good:** +**İyi:** ```javascript class SuperArray extends Array { @@ -726,15 +641,13 @@ class SuperArray extends Array { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Favor functional programming over imperative programming +### Zorunlu programlama yerine fonksiyonel programlamayı tercih edin -JavaScript isn't a functional language in the way that Haskell is, but it has -a functional flavor to it. Functional languages can be cleaner and easier to test. -Favor this style of programming when you can. +JavaScript, Haskell'in olduğu gibi işlevsel bir dil değildir, ancak işlevsel bir tadı vardır. İşlevsel diller daha temiz ve test edilmesi daha kolay olabilir. Yapabildiğinizde bu tarz bir programlama yapın. -**Bad:** +**Kötü:** ```javascript const programmerOutput = [ @@ -763,7 +676,7 @@ for (let i = 0; i < programmerOutput.length; i++) { } ``` -**Good:** +**İyi:** ```javascript const programmerOutput = [ @@ -791,11 +704,11 @@ const totalOutput = programmerOutput.reduce( ); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Encapsulate conditionals +### Koşulları kapsamak -**Bad:** +**Kötü:** ```javascript if (fsm.state === "fetching" && isEmpty(listNode)) { @@ -803,7 +716,7 @@ if (fsm.state === "fetching" && isEmpty(listNode)) { } ``` -**Good:** +**İyi:** ```javascript function shouldShowSpinner(fsm, listNode) { @@ -815,11 +728,11 @@ if (shouldShowSpinner(fsmInstance, listNodeInstance)) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** ### Avoid negative conditionals -**Bad:** +**Kötü:** ```javascript function isDOMNodeNotPresent(node) { @@ -831,7 +744,7 @@ if (!isDOMNodeNotPresent(node)) { } ``` -**Good:** +**İyi:** ```javascript function isDOMNodePresent(node) { @@ -843,20 +756,14 @@ if (isDOMNodePresent(node)) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid conditionals +### Koşullardan kaçının -This seems like an impossible task. Upon first hearing this, most people say, -"how am I supposed to do anything without an `if` statement?" The answer is that -you can use polymorphism to achieve the same task in many cases. The second -question is usually, "well that's great but why would I want to do that?" The -answer is a previous clean code concept we learned: a function should only do -one thing. When you have classes and functions that have `if` statements, you -are telling your user that your function does more than one thing. Remember, -just do one thing. +Bu imkansız bir görev gibi görünüyor. Bunu ilk kez duyduktan sonra, çoğu kişi "`if` ifadesi olmadan nasıl bir şey yapmam gerekiyor?" Cevap şu ki +birçok durumda aynı görevi yerine getirmek için polimorfizm kullanabilirsiniz. İkinci soru genellikle, "peki bu harika ama neden bunu yapmak isteyeyim ki?" Cevap, daha önce öğrendiğimiz temiz bir kod kavramıydı: bir fonksiyon sadece bir şey yapmalı. `If` ifadeleri olan sınıflarınız ve fonksiyonlarınız olduğunda, kullanıcılara işlevinizin birden fazla şey yaptığını söylüyor. Unutmayın, sadece bir şey yapın. -**Bad:** +**Kötü:** ```javascript class Airplane { @@ -874,7 +781,7 @@ class Airplane { } ``` -**Good:** +**İyi:** ```javascript class Airplane { @@ -903,16 +810,13 @@ class Cessna extends Airplane { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid type-checking (part 1) +### Yazım denetiminden kaçının (Bölüm 1) -JavaScript is untyped, which means your functions can take any type of argument. -Sometimes you are bitten by this freedom and it becomes tempting to do -type-checking in your functions. There are many ways to avoid having to do this. -The first thing to consider is consistent APIs. +JavaScript türsüzdür, yani işlevleriniz her türlü argümanı alabilir. Bazen bu özgürlük bizi oltaya getirebilir ve fonksiyonlarınızda tip kontrolü yapmak cazip hale gelir. Bunu yapmaktan kaçınmanın birçok yolu vardır. Dikkate alınması gereken ilk şey tutarlı API'lardır. -**Bad:** +**Kötü:** ```javascript function travelToTexas(vehicle) { @@ -924,7 +828,7 @@ function travelToTexas(vehicle) { } ``` -**Good:** +**İyi:** ```javascript function travelToTexas(vehicle) { @@ -932,21 +836,14 @@ function travelToTexas(vehicle) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid type-checking (part 2) +### Yazım denetiminden kaçının (Bölüm 2) -If you are working with basic primitive values like strings and integers, -and you can't use polymorphism but you still feel the need to type-check, -you should consider using TypeScript. It is an excellent alternative to normal -JavaScript, as it provides you with static typing on top of standard JavaScript -syntax. The problem with manually type-checking normal JavaScript is that -doing it well requires so much extra verbiage that the faux "type-safety" you get -doesn't make up for the lost readability. Keep your JavaScript clean, write -good tests, and have good code reviews. Otherwise, do all of that but with -TypeScript (which, like I said, is a great alternative!). +Dizeler ve tamsayılar gibi temel ilkel değerlerle çalışıyorsanız, +ve polimorfizm kullanamazsınız, ancak yine de yazım denetimi yapma gereğini hissediyorsanız, TypeScript kullanmayı düşünmelisiniz. Standart JavaScript sentaks üstünde statik yazım sağladığı için normal JavaScript'e mükemmel bir alternatiftir. Manuel olarak normal JavaScript'i kontrol etmeyle ilgili sorun, iyi yapmak o kadar fazla ayrıntılı gerektirir ki, elde ettiğiniz sahte "tip güvenliği" kaybettiğiniz okunabilirliği telafi etmez. JavaScript'inizi temiz tutun, iyi testler yazın ve iyi kod incelemelerine sahip olun. Aksi takdirde, hepsini TypeScript ile yapın (dediğim gibi harika bir alternatif!). -**Bad:** +**Kötü:** ```javascript function combine(val1, val2) { @@ -961,7 +858,7 @@ function combine(val1, val2) { } ``` -**Good:** +**İyi:** ```javascript function combine(val1, val2) { @@ -969,27 +866,25 @@ function combine(val1, val2) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** + +### Aşırı optimizasyon yapma -### Don't over-optimize +Modern tarayıcılar çalışma zamanında çok sayıda optimizasyon yapar. Çoğu zaman, eğer optimize ediyorsanız, sadece zamanınızı boşa harcıyorsunuz demektir. -Modern browsers do a lot of optimization under-the-hood at runtime. A lot of -times, if you are optimizing then you are just wasting your time. [There are good -resources](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) -for seeing where optimization is lacking. Target those in the meantime, until -they are fixed if they can be. +Optimizasyonun nerede olmadığını görmek için [iyi kaynaklar](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) vardır. Bunları optimize edene kadar işaretleyebilirsiniz. -**Bad:** +**Kötü:** ```javascript -// On old browsers, each iteration with uncached `list.length` would be costly -// because of `list.length` recomputation. In modern browsers, this is optimized. +// Eski tarayıcılarda, önbelleğe alınmamış "list.length" içeren her yineleme maliyetli olacaktır +// list.length yeniden hesaplanması nedeniyle. Modern tarayıcılarda bu optimize edilmiştir. for (let i = 0, len = list.length; i < len; i++) { // ... } ``` -**Good:** +**İyi:** ```javascript for (let i = 0; i < list.length; i++) { @@ -997,15 +892,13 @@ for (let i = 0; i < list.length; i++) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Remove dead code +### Kullanılmayan kodları silin -Dead code is just as bad as duplicate code. There's no reason to keep it in -your codebase. If it's not being called, get rid of it! It will still be safe -in your version history if you still need it. +Ölü kod, yinelenen kod kadar kötü. Kod tabanınızda tutmak için bir neden yoktur. Eğer çağrılmazsa, ondan kurtulun! Hala ihtiyacınız varsa sürüm geçmişinizde güvende olacaktır. -**Bad:** +**Kötü:** ```javascript function oldRequestModule(url) { @@ -1020,7 +913,7 @@ const req = newRequestModule; inventoryTracker("apples", req, "www.inventory-awesome.io"); ``` -**Good:** +**İyi:** ```javascript function newRequestModule(url) { @@ -1031,25 +924,21 @@ const req = newRequestModule; inventoryTracker("apples", req, "www.inventory-awesome.io"); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Objects and Data Structures** +## **Nesneler ve Veri Yapıları** -### Use getters and setters +### Alıcıları ve ayarlayıcıları kullanma (Getters & Setters) -Using getters and setters to access data on objects could be better than simply -looking for a property on an object. "Why?" you might ask. Well, here's an -unorganized list of reasons why: +Nesnelerdeki verilere erişmek için alıcıları ve ayarlayıcıları kullanmak, bir nesnedeki bir özelliği aramaktan daha iyi olabilir. "Neden?" sorabilirsiniz. Pekala, işte organize edilmeden nedenlerin bir listesi: -- When you want to do more beyond getting an object property, you don't have - to look up and change every accessor in your codebase. -- Makes adding validation simple when doing a `set`. -- Encapsulates the internal representation. -- Easy to add logging and error handling when getting and setting. -- You can lazy load your object's properties, let's say getting it from a - server. +- Bir nesne özelliği almanın ötesinde daha fazlasını yapmak istediğinizde, kod tabanınızdaki her erişimciye bakmanız ve değiştirmeniz gerekmez. +- `set`yaparken doğrulama basitçe yapılabilir. +- Dahili gösterimi içine alır. +- Alma ve ayarlama sırasında kayıtlamayı(logging) ve hata yönetimi(error handling) eklemek kolaydır. +- Diyelimki sunucudan alıyorsunuz, nesnenizin özelliklerini tembel(lazy load) olarak yükleyebilirsiniz. -**Bad:** +**Kötü:** ```javascript function makeBankAccount() { @@ -1065,19 +954,19 @@ const account = makeBankAccount(); account.balance = 100; ``` -**Good:** +**İyi:** ```javascript function makeBankAccount() { - // this one is private + // Bu fonksiyon özelinde (private) let balance = 0; - // a "getter", made public via the returned object below + // "alıcı"yı, genel(public) objeyi döndürerek yap function getBalance() { return balance; } - - // a "setter", made public via the returned object below + + // "ayarlayıcı"yı, genel(public) objeyi döndürerek yap function setBalance(amount) { // ... validate before updating the balance balance = amount; @@ -1094,13 +983,13 @@ const account = makeBankAccount(); account.setBalance(100); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Make objects have private members +### Nesnelerin özel üyeleri olmasını sağlama This can be accomplished through closures (for ES5 and below). -**Bad:** +**Kötü:** ```javascript const Employee = function(name) { @@ -1117,7 +1006,7 @@ delete employee.name; console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined ``` -**Good:** +**İyi:** ```javascript function makeEmployee(name) { @@ -1134,18 +1023,15 @@ delete employee.name; console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Classes** +## **Sınıflar** -### Prefer ES2015/ES6 classes over ES5 plain functions +### ES5 düz fonksiyonlar yerine ES2015 / ES6 sınıflarını tercih et -It's very difficult to get readable class inheritance, construction, and method -definitions for classical ES5 classes. If you need inheritance (and be aware -that you might not), then prefer ES2015/ES6 classes. However, prefer small functions over -classes until you find yourself needing larger and more complex objects. +Klasik ES5 sınıfları için okunabilir sınıf mirası, yapısı ve yöntem tanımları almak çok zordur. Miras almaya(inheritance) ihtiyacınız varsa (ve gerekmeyebileceğini unutmayın), ES2015 / ES6 sınıflarını tercih edin. Bununla birlikte, kendinizi daha büyük ve daha karmaşık nesnelere ihtiyaç duyana kadar küçük işlevlere tercih edin. -**Bad:** +**Kötü:** ```javascript const Animal = function(age) { @@ -1185,7 +1071,7 @@ Human.prototype.constructor = Human; Human.prototype.speak = function speak() {}; ``` -**Good:** +**İyi:** ```javascript class Animal { @@ -1221,17 +1107,13 @@ class Human extends Mammal { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use method chaining +### Yöntem zincirini kullan -This pattern is very useful in JavaScript and you see it in many libraries such -as jQuery and Lodash. It allows your code to be expressive, and less verbose. -For that reason, I say, use method chaining and take a look at how clean your code -will be. In your class functions, simply return `this` at the end of every function, -and you can chain further class methods onto it. +Bu desen JavaScript'te çok kullanışlıdır ve jQuery ve Lodash gibi birçok kütüphanede görürsünüz. Kodunuzun etkileyici ve daha az detaylı olmasını sağlar. Bu nedenle, diyorum ki, yöntem zincirleme kullanın ve kodunuzun ne kadar temiz olacağını göreceksiniz. Sınıf fonksiyonlarınızda, her fonksiyonun sonunda `this`'i döndürmeniz yeterlidir ve daha fazla sınıf yöntemini buna zincirleyebilirsiniz. -**Bad:** +**Kötü:** ```javascript class Car { @@ -1263,7 +1145,7 @@ car.setColor("pink"); car.save(); ``` -**Good:** +**İyi:** ```javascript class Car { @@ -1275,25 +1157,25 @@ class Car { setMake(make) { this.make = make; - // NOTE: Returning this for chaining + // NOT: Zincirleme için `this` döndür return this; } setModel(model) { this.model = model; - // NOTE: Returning this for chaining + // NOT: Zincirleme için `this` döndür return this; } setColor(color) { this.color = color; - // NOTE: Returning this for chaining + // NOT: Zincirleme için `this` döndür return this; } save() { console.log(this.make, this.model, this.color); - // NOTE: Returning this for chaining + // NOT: Zincirleme için `this` döndür return this; } } @@ -1301,28 +1183,19 @@ class Car { const car = new Car("Ford", "F-150", "red").setColor("pink").save(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Prefer composition over inheritance +### Miras yerine kompozisyon tercih et -As stated famously in [_Design Patterns_](https://en.wikipedia.org/wiki/Design_Patterns) by the Gang of Four, -you should prefer composition over inheritance where you can. There are lots of -good reasons to use inheritance and lots of good reasons to use composition. -The main point for this maxim is that if your mind instinctively goes for -inheritance, try to think if composition could model your problem better. In some -cases it can. +Dörtlü çete tarafından başlatılan ünlü [_Tasarım Desenleri_](https://en.wikipedia.org/wiki/Design_Patterns) gibi, siz de kompozisyonu, miras bırakmaya yerine göre tercih etmelisiniz. Miras kullanmak için birçok iyi neden ve kompozisyon kullanmak için birçok iyi neden vardır. Bu maksimum nokta için ana nokta, zihniniz içgüdüsel olarak miras kullanma için giderse, kompozisyon sorununuzu daha iyi modelleyip değiştiremeyeceğini düşünmeye çalışın. Bazı durumlarda olabilir. -You might be wondering then, "when should I use inheritance?" It -depends on your problem at hand, but this is a decent list of when inheritance -makes more sense than composition: +O zaman "ne zaman miras kullanmalıyım?" diye merak ediyor olabilirsiniz. O eldeki probleminize bağlıdır, ancak bu mirasın kompozisyondan daha mantıklı olduğu iyi bir listedir: -1. Your inheritance represents an "is-a" relationship and not a "has-a" - relationship (Human->Animal vs. User->UserDetails). -2. You can reuse code from the base classes (Humans can move like all animals). -3. You want to make global changes to derived classes by changing a base class. - (Change the caloric expenditure of all animals when they move). +1. Mirasınız "has-a" değil, "is-a" ilişkisini temsil eder ilişki (İnsan-> Hayvan ve Kullanıcı-> KullanıcıAyrıntıları). +2. Temel sınıflardan kodu yeniden kullanabilirsiniz (İnsanlar tüm hayvanlar gibi hareket edebilir). +3. Temel sınıfı değiştirerek türetilmiş sınıflarda genel değişiklikler yapmak istiyorsunuz. (Hareket ettiklerinde tüm hayvanların kalori harcamalarını değiştirin). -**Bad:** +**Kötü:** ```javascript class Employee { @@ -1334,7 +1207,7 @@ class Employee { // ... } -// Bad because Employees "have" tax data. EmployeeTaxData is not a type of Employee +// Kötü çünkü Çalışanların(Employees) vergi bilgisi 'var'. ÇalışanVergiBilgisi(EmployeeTaxData) bir çeşit Çalışan(Employee) değil. class EmployeeTaxData extends Employee { constructor(ssn, salary) { super(); @@ -1346,7 +1219,7 @@ class EmployeeTaxData extends Employee { } ``` -**Good:** +**İyi:** ```javascript class EmployeeTaxData { @@ -1371,22 +1244,15 @@ class Employee { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** ## **SOLID** -### Single Responsibility Principle (SRP) +### Tek Sorumluluk İlkesi (SRP) -As stated in Clean Code, "There should never be more than one reason for a class -to change". It's tempting to jam-pack a class with a lot of functionality, like -when you can only take one suitcase on your flight. The issue with this is -that your class won't be conceptually cohesive and it will give it many reasons -to change. Minimizing the amount of times you need to change a class is important. -It's important because if too much functionality is in one class and you modify -a piece of it, it can be difficult to understand how that will affect other -dependent modules in your codebase. +Temiz Kod'da belirtildiği gibi, "Bir sınıfın değişmesi için asla birden fazla sebep olmamalıdır". Bir sınıfı tıklım tıklım bir çok işlevsellikle doldurmak çekici gelebilir, tıpkı uçuşlarda yanına alabileceğiniz bir valiz gibi. Bununla ilgili sorun, sınıfınızın kavramsal olarak uyumlu olmayacağı ve değişmesi için birçok neden vereceği yönündedir. Bir sınıfı değiştirmek için ihtiyaç duyduğunuz sayıyı en aza indirmek önemlidir. Bir sınıfta çok fazla işlevsellik varsa ve bir parçasını değiştirirseniz, bunun kod tabanınızdaki diğer bağımlı modülleri nasıl etkileyeceğini anlamak zor olabilir. -**Bad:** +**Kötü:** ```javascript class UserSettings { @@ -1406,7 +1272,7 @@ class UserSettings { } ``` -**Good:** +**İyi:** ```javascript class UserAuth { @@ -1433,16 +1299,13 @@ class UserSettings { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Open/Closed Principle (OCP) +### Açık / Kapalı Prensibi (OCP) -As stated by Bertrand Meyer, "software entities (classes, modules, functions, -etc.) should be open for extension, but closed for modification." What does that -mean though? This principle basically states that you should allow users to -add new functionalities without changing existing code. +Bertrand Meyer tarafından belirtildiği gibi, "yazılım varlıkları (sınıflar, modüller, işlevler, vb.) Genişletme için açık, ancak değişiklik için kapalı olmalıdır." Bu ne anlama geliyor? Bu ilke, temel olarak kullanıcıların mevcut kodu değiştirmeden yeni işlevler eklemelerine izin vermeniz gerektiğini belirtir. -**Bad:** +**Kötü:** ```javascript class AjaxAdapter extends Adapter { @@ -1486,7 +1349,7 @@ function makeHttpCall(url) { } ``` -**Good:** +**İyi:** ```javascript class AjaxAdapter extends Adapter { @@ -1524,24 +1387,15 @@ class HttpRequester { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Liskov Substitution Principle (LSP) +### Liskov’un Yerine Geçme Prensibi (LSP) -This is a scary term for a very simple concept. It's formally defined as "If S -is a subtype of T, then objects of type T may be replaced with objects of type S -(i.e., objects of type S may substitute objects of type T) without altering any -of the desirable properties of that program (correctness, task performed, -etc.)." That's an even scarier definition. +Bu çok basit bir kavram için korkutucu bir terimdir.Resmi olarak "S, T'nin bir alt tipiyse, o zaman T tipi nesnelerin yerine S tipi nesneler (yani, S tipi nesneler T programındaki nesnelerin yerine geçebilir), bu programın istenen özelliklerini değiştirmeden değiştirilebilir (doğruluk, yapılan görev vb.) " Bu daha da korkunç bir tanım. -The best explanation for this is if you have a parent class and a child class, -then the base class and child class can be used interchangeably without getting -incorrect results. This might still be confusing, so let's take a look at the -classic Square-Rectangle example. Mathematically, a square is a rectangle, but -if you model it using the "is-a" relationship via inheritance, you quickly -get into trouble. +Bunun için en iyi açıklama, bir üst sınıfınız ve bir alt sınıfınız varsa, temel sınıf ve alt sınıf yanlış sonuçlar elde etmeden birbirinin yerine kullanılabilir.Bu hala kafa karıştırıcı olabilir, bu yüzden klasik Kare Dikdörtgen örneğine bakalım. Matematiksel olarak, bir kare bir dikdörtgendir, ancak miras yoluyla "is-a" ilişkisini kullanarak model verirseniz, hızlı bir şekilde sorun yaşarsınız. -**Bad:** +**Kötü:** ```javascript class Rectangle { @@ -1587,7 +1441,7 @@ function renderLargeRectangles(rectangles) { rectangles.forEach(rectangle => { rectangle.setWidth(4); rectangle.setHeight(5); - const area = rectangle.getArea(); // BAD: Returns 25 for Square. Should be 20. + const area = rectangle.getArea(); // KÖTÜ: Kare için 25 değerini döndürür. 20 olmalı. rectangle.render(area); }); } @@ -1596,7 +1450,7 @@ const rectangles = [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles(rectangles); ``` -**Good:** +**İyi:** ```javascript class Shape { @@ -1643,25 +1497,17 @@ const shapes = [new Rectangle(4, 5), new Rectangle(4, 5), new Square(5)]; renderLargeShapes(shapes); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Interface Segregation Principle (ISP) +### Arayüzlerin Ayrımı Prensibi (ISP) -JavaScript doesn't have interfaces so this principle doesn't apply as strictly -as others. However, it's important and relevant even with JavaScript's lack of -type system. +JavaScript'in arayüzleri yoktur, bu nedenle bu ilke diğerleri kadar kesin olarak geçerli değildir. Bununla birlikte, JavaScript'in tür sistemi eksikliğinde bile önemli ve alâkalıdır. -ISP states that "Clients should not be forced to depend upon interfaces that -they do not use." Interfaces are implicit contracts in JavaScript because of -duck typing. +ISP, "kullanıcılar kullanmadığı arabirimlere bağımlı olmaya zorlanmamalıdır." der. Arabirimler, `Duck Typing` yüzünden JavaScript'de üstü kapalı anlaşmalardır. -A good example to look at that demonstrates this principle in JavaScript is for -classes that require large settings objects. Not requiring clients to setup -huge amounts of options is beneficial, because most of the time they won't need -all of the settings. Making them optional helps prevent having a -"fat interface". +Bu ilkeyi JavaScript'te gösteren iyi bir örnek, sınıflar büyük ayar nesneleri gerektirir. Kullanıcıların büyük miktarda seçenek ayarlamalarını istememek gerekli değildir, çünkü çoğu zaman tüm ayarlara ihtiyaç duymazlar. Bunları isteğe bağlı yapmak, bir "büyük arayüzü" olmasını önlemeye yardımcı olur. -**Bad:** +**Kötü:** ```javascript class DOMTraverser { @@ -1682,12 +1528,12 @@ class DOMTraverser { const $ = new DOMTraverser({ rootNode: document.getElementsByTagName("body"), - animationModule() {} // Most of the time, we won't need to animate when traversing. + animationModule() {} // Coğunlukla, bunu canlandırmamız gerekmeyecek // ... }); ``` -**Good:** +**İyi:** ```javascript class DOMTraverser { @@ -1721,32 +1567,24 @@ const $ = new DOMTraverser({ }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Dependency Inversion Principle (DIP) +### Bağlılığı Tersine Çevirme Prensibi (DIP) -This principle states two essential things: +Bu ilke iki temel şeyi ifade eder: -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. +1. Yüksek seviyeli modüller, düşük seviyeli modüllere bağlı olmamalıdır. Her ikisi de soyutlamalara bağlı olmalıdır. +2. Soyutlamalar detaylara bağlı olmamalıdır. Ayrıntılar soyutlamalara bağlı olmalıdır. -This can be hard to understand at first, but if you've worked with AngularJS, -you've seen an implementation of this principle in the form of Dependency -Injection (DI). While they are not identical concepts, DIP keeps high-level -modules from knowing the details of its low-level modules and setting them up. -It can accomplish this through DI. A huge benefit of this is that it reduces -the coupling between modules. Coupling is a very bad development pattern because -it makes your code hard to refactor. +İlk başta bunu anlamak zor olabilir, ancak AngularJS ile çalıştıysanız, bu prensibin Bağımlılık Enjeksiyonu (DI) şeklinde bir uygulamasını gördünüz. Aynı kavramlar olmasalar da, DIP yüksek seviyede modüllerin düşük seviyeli modüllerinin detaylarını bilmelerini ve ayarlamalarını sağlar. +Bunu DI ile başarabilir. Bunun büyük bir yararı, modüller arasındaki bağlantıyı azaltmasıdır. Eşleştirme(Coupling) çok kötü bir gelişme modelidir çünkü +kodunuzu yeniden düzenleme zorlaştırır. -As stated previously, JavaScript doesn't have interfaces so the abstractions -that are depended upon are implicit contracts. That is to say, the methods -and properties that an object/class exposes to another object/class. In the -example below, the implicit contract is that any Request module for an -`InventoryTracker` will have a `requestItems` method. +Daha önce belirtildiği gibi, JavaScript'in arayüzleri yoktur, bu nedenle soyutlamalar örtük sözleşmelere bağlıdır. +Yani, bir nesnenin / sınıfın başka bir nesneye / sınıfa maruz bıraktığı yöntemler ve özellikler. +Aşağıdaki örnekte, örtük sözleşme, bir `InventoryTracker` için herhangi bir Request modülünün `requestItems` yöntemine sahip olacağıdır. -**Bad:** +**Kötü:** ```javascript class InventoryRequester { @@ -1763,8 +1601,8 @@ class InventoryTracker { constructor(items) { this.items = items; - // BAD: We have created a dependency on a specific request implementation. - // We should just have requestItems depend on a request method: `request` + // KÖTÜ: Belirli bir istek uygulamasına bağımlılık yarattık. +    // requestItems sadece `request` 'e bağlımlı olmalıdır. this.requester = new InventoryRequester(); } @@ -1779,7 +1617,7 @@ const inventoryTracker = new InventoryTracker(["apples", "bananas"]); inventoryTracker.requestItems(); ``` -**Good:** +**İyi:** ```javascript class InventoryTracker { @@ -1815,8 +1653,8 @@ class InventoryRequesterV2 { } } -// By constructing our dependencies externally and injecting them, we can easily -// substitute our request module for a fancy new one that uses WebSockets. +// Bağımlılıklarımızı harici olarak yapılandırarak ve enjekte ederek +// istek modülümüzü WebSockets kullanan yeni ve havalı bir modülle kolayca değiştirebiliriz. const inventoryTracker = new InventoryTracker( ["apples", "bananas"], new InventoryRequesterV2() @@ -1824,28 +1662,19 @@ const inventoryTracker = new InventoryTracker( inventoryTracker.requestItems(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** + +## **Testler** -## **Testing** +Test etmek canlıya çıkmaktan bile önemlidir. Eğer testiniz yoksa veya yetersiz bir miktardaysa, kodu her gönderdiğinizde hiçbir şeyin bozulmadığına emin olmazsınız. Neyin yeterli bir miktar oluşturduğuna karar vermek takımınıza bağlıdır, %100 kapsama sahip olmak (tüm ifadeler ve şubeler) size güven ve gönül rahatlığı sağlar. Bu, harika bir test framework'üne sahip olmanın yanı sıra, [iyi bir kapsama aracı](https://gotwarlost.github.io/istanbul/) kullanmanız gerektiği anlamına gelir -Testing is more important than shipping. If you have no tests or an -inadequate amount, then every time you ship code you won't be sure that you -didn't break anything. Deciding on what constitutes an adequate amount is up -to your team, but having 100% coverage (all statements and branches) is how -you achieve very high confidence and developer peace of mind. This means that -in addition to having a great testing framework, you also need to use a -[good coverage tool](https://gotwarlost.github.io/istanbul/). +Test yazmamanın mazereti yoktur. Çok sayıda [iyi JS test framework'ü](https://jstherightway.org/#testing-tools) vardır, bu yüzden ekibinize uyan birini bulun. -There's no excuse to not write tests. There are [plenty of good JS test frameworks](https://jstherightway.org/#testing-tools), so find one that your team prefers. -When you find one that works for your team, then aim to always write tests -for every new feature/module you introduce. If your preferred method is -Test Driven Development (TDD), that is great, but the main point is to just -make sure you are reaching your coverage goals before launching any feature, -or refactoring an existing one. +Ekibiniz için uygun olanı bulduğunuzda, kullanılan her yeni özellik / modül için daima testler yazmayı hedefleyin. Tercih ettiğiniz yöntem Test Odaklı Geliştirme (TDD) ise, bu harika, ancak asıl mesele, herhangi bir özelliği başlatmadan veya mevcut bir özelliği yeniden düzenlemeden önce kapsama hedeflerinize ulaştığınızdan emin olmaktır. -### Single concept per test +### Her test için tek konsept -**Bad:** +**Kötü:** ```javascript import assert from "assert"; @@ -1869,7 +1698,7 @@ describe("MomentJS", () => { }); ``` -**Good:** +**İyi:** ```javascript import assert from "assert"; @@ -1895,16 +1724,15 @@ describe("MomentJS", () => { }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Concurrency** +## **Tutarlılık** -### Use Promises, not callbacks +### Promises kullanın, callback değil -Callbacks aren't clean, and they cause excessive amounts of nesting. With ES2015/ES6, -Promises are a built-in global type. Use them! +'Callback'ler temiz değildir ve aşırı miktarda iç içe geçmeye neden olurlar. ES2015 / ES6 ile Promise'ler yerleşik bir global tiptir. Onları kullan! -**Bad:** +**Kötü:** ```javascript import { get } from "request"; @@ -1928,7 +1756,7 @@ get( ); ``` -**Good:** +**İyi:** ```javascript import { get } from "request-promise"; @@ -1946,17 +1774,13 @@ get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Async/Await are even cleaner than Promises +### Async/Await kullanmak Promis kullanmaktan bile daha temiz -Promises are a very clean alternative to callbacks, but ES2017/ES8 brings async and await -which offer an even cleaner solution. All you need is a function that is prefixed -in an `async` keyword, and then you can write your logic imperatively without -a `then` chain of functions. Use this if you can take advantage of ES2017/ES8 features -today! +Promise'ler callback'lere göte çok daha temiz alternatiflerdir, ama ES2017/ES8 async ve await getirdi ve bu daha temiz bir çözüm sunuyor. Tek yapmanız gereken fonksiyonun başına `async` eklemek ve sonrasında mantıksal kullanımızı `then` zinciri kulanmadan yazabilirsiniz. Bugün ES2017 / ES8 özelliklerinden yararlanabiliyorsanız bunu kullanın! -**Bad:** +**Kötü:** ```javascript import { get } from "request-promise"; @@ -1974,7 +1798,7 @@ get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") }); ``` -**Good:** +**İyi:** ```javascript import { get } from "request-promise"; @@ -1995,25 +1819,21 @@ async function getCleanCodeArticle() { getCleanCodeArticle() ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** + +## **Hata Yönetimi** + +Atılan hatalar iyi bir şey! Bunlar, programınızdaki bir şey yanlış gittiğinde çalışma zamanının başarıyla tanımlandığı anlamına gelir ve sizi geçerli yığında (stack) fonksiyonu çalıştırmayı, işlevi dururup size konsolda yığın izlemede haber vererek yapar. -## **Error Handling** +--- HERE -Thrown errors are a good thing! They mean the runtime has successfully -identified when something in your program has gone wrong and it's letting -you know by stopping function execution on the current stack, killing the -process (in Node), and notifying you in the console with a stack trace. +### Yakalanmış hataları görmemezlikten gelmeyin -### Don't ignore caught errors +Yakalanan bir hatayla hiçbir şey yapmamanız size söz konusu hatayı düzeltebilme veya tepki gösterme yeteneği vermez. Hatayı konsola (`console.log`) kaydetmek, konsola yazdırılan bir şey denizinde kaybolabileceği sıklıkta daha iyi değildir. -Doing nothing with a caught error doesn't give you the ability to ever fix -or react to said error. Logging the error to the console (`console.log`) -isn't much better as often times it can get lost in a sea of things printed -to the console. If you wrap any bit of code in a `try/catch` it means you -think an error may occur there and therefore you should have a plan, -or create a code path, for when it occurs. +Herhangi bir kod parçasını `try/catch` içerisinde kullanıyorsanız, orada bir hata olabileceğini düşündüğünüz anlamına gelir ve bu nedenle gerçekleştiği zaman için bir planınız olması veya bir kod yolu oluşturmanız gerekir. -**Bad:** +**Kötü:** ```javascript try { @@ -2023,28 +1843,27 @@ try { } ``` -**Good:** +**İyi:** ```javascript try { functionThatMightThrow(); } catch (error) { - // One option (more noisy than console.log): + // Bir secenek (console.log'dan daha dikkat çekici) console.error(error); - // Another option: + // Bir secenek daha notifyUserOfError(error); - // Another option: + // Bir secenek daha reportErrorToService(error); - // OR do all three! + // veya hepsini bir yapın } ``` -### Don't ignore rejected promises +### Reddedilmiş promisleri görmemezlikten gelmeyin -For the same reason you shouldn't ignore caught errors -from `try/catch`. +Aynı sebeplerden dolayı, `try/catch`'de oluşan hataları yok saymamalısınız -**Bad:** +**Kötü:** ```javascript getdata() @@ -2056,7 +1875,7 @@ getdata() }); ``` -**Good:** +**İyi:** ```javascript getdata() @@ -2064,36 +1883,29 @@ getdata() functionThatMightThrow(data); }) .catch(error => { - // One option (more noisy than console.log): + // Bir secenek (console.log'dan daha dikkat çekici) console.error(error); - // Another option: + // Bir secenek daha notifyUserOfError(error); - // Another option: + // Bir secenek daha reportErrorToService(error); - // OR do all three! + // veya hepsini bir yapın }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Formatting** +## **Biçimlendirme** -Formatting is subjective. Like many rules herein, there is no hard and fast -rule that you must follow. The main point is DO NOT ARGUE over formatting. -There are [tons of tools](https://standardjs.com/rules.html) to automate this. -Use one! It's a waste of time and money for engineers to argue over formatting. +Biçimlendirme özneldir. Buradaki birçok kural gibi, uygulamanız gereken zor ve hızlı bir kural yoktur. Ana nokta biçimlendirme üzerinde tartışma DEĞİLDİR. Bunu otomatikleştirmek için [tonlarca araç](https://standardjs.com/rules.html) vardır. Birini kullan! Mühendislerin biçimlendirme konusunda tartışmaları zaman ve para kaybıdır. -For things that don't fall under the purview of automatic formatting -(indentation, tabs vs. spaces, double vs. single quotes, etc.) look here -for some guidance. +Otomatik biçimlendirme (girintileme, sekmeler ve boşluklar, çift veya tek tırnak işaretleri vb.) Kapsamına girmeyen şeyler için bazı rehberlik için buraya bakın. -### Use consistent capitalization +### Tutarlı büyük harf kullanımı -JavaScript is untyped, so capitalization tells you a lot about your variables, -functions, etc. These rules are subjective, so your team can choose whatever -they want. The point is, no matter what you all choose, just be consistent. +JavaScript türsüzdür, bu nedenle büyük / küçük harf kullanımı değişkenleriniz, işlevleriniz vb. Hakkında çok şey anlatır. Bu kurallar özneldir, böylece ekibiniz istediklerini seçebilir. Mesele şu ki, ne seçerseniz seçin, tutarlı olun. -**Bad:** +**Kötü:** ```javascript const DAYS_IN_WEEK = 7; @@ -2109,7 +1921,7 @@ class animal {} class Alpaca {} ``` -**Good:** +**İyi:** ```javascript const DAYS_IN_WEEK = 7; @@ -2125,15 +1937,13 @@ class Animal {} class Alpaca {} ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Function callers and callees should be close +### Fonksion çağıranları ve çağrılanları yakın olmalı -If a function calls another, keep those functions vertically close in the source -file. Ideally, keep the caller right above the callee. We tend to read code from -top-to-bottom, like a newspaper. Because of this, make your code read that way. +Eğer bir fonksiyon diğer fonksiyonu çağırıyorsa, dikey olarak bu fonksiyonları kaynak dosyasında yakın tutun. İdeal olan, fonksiyonu kullanan kullandığı fonksiyonun hemen üstünde olmasıdır. We tend to read code from top-to-bottom, like a newspaper.Bu nedenle, kodunuzu bu şekilde okuyun. -**Bad:** +**Kötü:** ```javascript class PerformanceReview { @@ -2173,7 +1983,7 @@ const review = new PerformanceReview(employee); review.perfReview(); ``` -**Good:** +**İyi:** ```javascript class PerformanceReview { @@ -2213,37 +2023,37 @@ const review = new PerformanceReview(employee); review.perfReview(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Comments** +## **Yorumlar** -### Only comment things that have business logic complexity. +### Yalnızca iş mantığı karmaşıklığı olan şeyleri yorumlayın -Comments are an apology, not a requirement. Good code _mostly_ documents itself. +Yorumlar aslında bir özür, şart değil. İyi kod _çoğunlukla_ kendini belgelemektedir. -**Bad:** +**Kötü:** ```javascript function hashIt(data) { - // The hash + // Karma let hash = 0; - // Length of string + // String uzunluğu const length = data.length; - // Loop through every character in data + // Verilerdeki her karakteri gözden geçirin for (let i = 0; i < length; i++) { - // Get character code. + // Karakter kodunu al const char = data.charCodeAt(i); - // Make the hash + // Karıştır hash = (hash << 5) - hash + char; - // Convert to 32-bit integer + // 32-bit tam sayıya dönüştür hash &= hash; } } ``` -**Good:** +**İyi:** ```javascript function hashIt(data) { @@ -2254,19 +2064,19 @@ function hashIt(data) { const char = data.charCodeAt(i); hash = (hash << 5) - hash + char; - // Convert to 32-bit integer + // 32-bit tam sayıya dönüştür hash &= hash; } } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Don't leave commented out code in your codebase +### Kodlarınızı yorum olarak bırakmayın -Version control exists for a reason. Leave old code in your history. +Versiyon kontrol'un var olmasının bir sebebi var. Eski kodlarınızı tarihin tozlu sayfalarında bırakın. -**Bad:** +**Kötü:** ```javascript doStuff(); @@ -2275,20 +2085,19 @@ doStuff(); // doSoMuchStuff(); ``` -**Good:** +**İyi:** ```javascript doStuff(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Don't have journal comments +### Günlük yorumları yapmayın -Remember, use version control! There's no need for dead code, commented code, -and especially journal comments. Use `git log` to get history! +Hatırlayın, versiyon kontrol kullanın! Kullanılmayan koda, yoruma alınmış koda ve özellikle günlük kodlarına gerek yok. Geçmiş için `git log` kullanın. -**Bad:** +**Kötü:** ```javascript /** @@ -2302,7 +2111,7 @@ function combine(a, b) { } ``` -**Good:** +**İyi:** ```javascript function combine(a, b) { @@ -2310,14 +2119,13 @@ function combine(a, b) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid positional markers +### Yer belirleyicilerden kaçının -They usually just add noise. Let the functions and variable names along with the -proper indentation and formatting give the visual structure to your code. +Bunlar genellikle kirlilik yaratır. Fonksiyonların ve değişken adlarının yanı sıra uygun girinti ve biçimlendirme kodunuza görsel yapı kazandırsın. -**Bad:** +**Kötü:** ```javascript //////////////////////////////////////////////////////////////////////////////// @@ -2336,7 +2144,7 @@ const actions = function() { }; ``` -**Good:** +**İyi:** ```javascript $scope.model = { @@ -2349,11 +2157,11 @@ const actions = function() { }; ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## Translation +## Çeviriler -This is also available in other languages: +Ayrıca diğer dillerde de: - ![am](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Armenia.png) **Armenian**: [hanumanum/clean-code-javascript/](https://github.com/hanumanum/clean-code-javascript) - ![bd](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bangladesh.png) **Bangla(বাংলা)**: [InsomniacSabbir/clean-code-javascript/](https://github.com/InsomniacSabbir/clean-code-javascript/) @@ -2374,6 +2182,7 @@ This is also available in other languages: - [maksugr/clean-code-javascript](https://github.com/maksugr/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [tureey/clean-code-javascript](https://github.com/tureey/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Uruguay.png) **Spanish**: [andersontr15/clean-code-javascript](https://github.com/andersontr15/clean-code-javascript-es) +- ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** From 87185d9b797a1de7d48902f6561a20f79a64c8e3 Mon Sep 17 00:00:00 2001 From: Burak Sonmez Date: Thu, 26 Mar 2020 08:42:09 +0300 Subject: [PATCH 10/24] Revert "turkish added" This reverts commit 2edfeef74002f7aeaa15a7bea4adb047b85dd539. --- README.md | 901 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 546 insertions(+), 355 deletions(-) diff --git a/README.md b/README.md index d7747ff9..bbe7a083 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,69 @@ # clean-code-javascript -## İçindekiler +## Table of Contents -1. [Giriş](#Giriş) -2. [Değişkenler](#Değişkenler) -3. [Fonksiyonlar](#Fonksiyonlar) -4. [Nesneler ve Veri Yapıları](#nesneler-ve-veri-yapıları) -5. [Sınıflar (Class)](#sınıflar) +1. [Introduction](#introduction) +2. [Variables](#variables) +3. [Functions](#functions) +4. [Objects and Data Structures](#objects-and-data-structures) +5. [Classes](#classes) 6. [SOLID](#solid) -7. [Testler](#testler) -8. [Tutarlılık](#Tutarlılık) -9. [Hata Yönetimi](#Hata-Yönetimi) -10. [Biçimlendirme](#Biçimlendirme) -11. [Yorumlar](#yorumlar) -12. [Çeviriler](#çeviriler) +7. [Testing](#testing) +8. [Concurrency](#concurrency) +9. [Error Handling](#error-handling) +10. [Formatting](#formatting) +11. [Comments](#comments) +12. [Translation](#translation) -## Giriş +## Introduction -![Kod okurken kaç defa bağıracağınızın bir sayısı olarak yazılım kalite tahmininin görüntüsü](https://www.osnews.com/images/comics/wtfm.jpg) +![Humorous image of software quality estimation as a count of how many expletives +you shout when reading code](https://www.osnews.com/images/comics/wtfm.jpg) -Robert C. Martin'nın kitabı olan ve yazılım mühendisliği ilkerini barındıran [_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)'un JavaScript için uyarlanmış hali. Bu bir tarz rehberi değil. JavaScript'te [okunabilir, yeniden kullanılabilir ve yeniden düzenlenebilir](https://github.com/ryanmcdermott/3rs-of-software-architecture) yazılımlar üretmeye yönelik bir kılavuzdur. +Software engineering principles, from Robert C. Martin's book +[_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882), +adapted for JavaScript. This is not a style guide. It's a guide to producing +[readable, reusable, and refactorable](https://github.com/ryanmcdermott/3rs-of-software-architecture) software in JavaScript. -Buradaki her ilkeye kesinlikle uyulmak zorunda değildir ve daha azı evrensel olarak kabul edilecektir. Bunlar önerilerden başka bir şey değildir, fakat bunlar _Clean Code_ yazarları tarafından uzun yıllar süren tecrübeler ile kodlandı. +Not every principle herein has to be strictly followed, and even fewer will be +universally agreed upon. These are guidelines and nothing more, but they are +ones codified over many years of collective experience by the authors of +_Clean Code_. -Yazılım mühendisliği zanaatımız 50 yaşın biraz üzerinde ve hala çok şey öğreniyoruz. Yazılım mimarisi, mimarinin kendisi kadar eski olduğunda, belki de takip edilmesi daha zor kurallarımız olacak. Şimdi, bu önerilerin sizin ve ekibinizin ürettiği JavaScript kodunun kalitesini değerlendirmek için bir mihenk taşı işlevi görmesine izin verin. +Our craft of software engineering is just a bit over 50 years old, and we are +still learning a lot. When software architecture is as old as architecture +itself, maybe then we will have harder rules to follow. For now, let these +guidelines serve as a touchstone by which to assess the quality of the +JavaScript code that you and your team produce. -Bir şey daha: bunların bilinmesi sizi hemen daha iyi bir yazılım geliştiricisi yapmaz ve uzun yıllar onlarla çalışmak hata yapmayacağınız anlamına gelmez. +One more thing: knowing these won't immediately make you a better software +developer, and working with them for many years doesn't mean you won't make +mistakes. Every piece of code starts as a first draft, like wet clay getting +shaped into its final form. Finally, we chisel away the imperfections when +we review it with our peers. Don't beat yourself up for first drafts that need +improvement. Beat up the code instead! -Her kod parçası ilk taslak olarak başlar, örneğin ıslak kil son halini alır. Son olarak, akranlarımızla gözden geçirdiğimizde kusurları kesiyoruz. İyileştirilmesi gereken ilk taslaklar için kendinize yüklenmeyin. Onun yerine kodunuza yüklenin. +## **Variables** -## **Değişkenler** +### Use meaningful and pronounceable variable names -### Anlamlı ve belirgin değişken adları kullanın - -**Kötü:** +**Bad:** ```javascript const yyyymmdstr = moment().format("YYYY/MM/DD"); ``` -**İyi:** +**Good:** ```javascript const currentDate = moment().format("YYYY/MM/DD"); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Aynı değişken türü için aynı kelimeleri kullanın +### Use the same vocabulary for the same type of variable -**Kötü:** +**Bad:** ```javascript getUserInfo(); @@ -57,41 +71,45 @@ getClientData(); getCustomerRecord(); ``` -**İyi:** +**Good:** ```javascript getUser(); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Aranabilir isimler kullanın +### Use searchable names -Yazacağımızdan daha fazla kod okuyacağız. Yazdığımız kodun okunabilir ve aranabilir olması önemlidir. Değişkenleri anlamlı ve anlaşılabilir _isimlendirmemekle_, okuyucuya zarar veriyoruz. -Adlarınızı aranabilir hale getirin. [buddy.js](https://github.com/danielstjules/buddy.js) ve -[ESLint](https://github.com/eslint/eslint/blob/660e0918933e6e7fede26bc675a0763a6b357c94/docs/rules/no-magic-numbers.md) gibi araçlar isimlendirilmemiş sabitlerinizi belirlemenize yardımcı olacaktır. +We will read more code than we will ever write. It's important that the code we +do write is readable and searchable. By _not_ naming variables that end up +being meaningful for understanding our program, we hurt our readers. +Make your names searchable. Tools like +[buddy.js](https://github.com/danielstjules/buddy.js) and +[ESLint](https://github.com/eslint/eslint/blob/660e0918933e6e7fede26bc675a0763a6b357c94/docs/rules/no-magic-numbers.md) +can help identify unnamed constants. -**Kötü:** +**Bad:** ```javascript -// 86400000 neydi ? +// What the heck is 86400000 for? setTimeout(blastOff, 86400000); ``` -**İyi:** +**Good:** ```javascript -// Bunları büyük harfle adlandırılmış sabitler olarak bildirin. +// Declare them as capitalized named constants. const MILLISECONDS_IN_A_DAY = 86_400_000; setTimeout(blastOff, MILLISECONDS_IN_A_DAY); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Açıklayıcı değişkenler kullan +### Use explanatory variables -**Kötü:** +**Bad:** ```javascript const address = "One Infinite Loop, Cupertino 95014"; @@ -102,7 +120,7 @@ saveCityZipCode( ); ``` -**İyi:** +**Good:** ```javascript const address = "One Infinite Loop, Cupertino 95014"; @@ -111,13 +129,13 @@ const [_, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Kafadan planmaktan kaçının +### Avoid Mental Mapping -Açık olmak, ima etmekten iyidir. +Explicit is better than implicit. -**Kötü:** +**Bad:** ```javascript const locations = ["Austin", "New York", "San Francisco"]; @@ -127,12 +145,12 @@ locations.forEach(l => { // ... // ... // ... - // Bir dakika, 'l' neydi? + // Wait, what is `l` for again? dispatch(l); }); ``` -**İyi:** +**Good:** ```javascript const locations = ["Austin", "New York", "San Francisco"]; @@ -146,13 +164,14 @@ locations.forEach(location => { }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Gereksiz içerikler eklemeyin +### Don't add unneeded context -Sınıf / nesne adınız size bir şey söylüyorsa, bunu değişken adınızda tekrarlamayın. +If your class/object name tells you something, don't repeat that in your +variable name. -**Kötü:** +**Bad:** ```javascript const Car = { @@ -166,7 +185,7 @@ function paintCar(car) { } ``` -**İyi:** +**Good:** ```javascript const Car = { @@ -180,13 +199,16 @@ function paintCar(car) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Kısa devre veya şartlar yerine önceden tanımlanmış argümanlar kullanın +### Use default arguments instead of short circuiting or conditionals -Önceden tanımlanan argümanlar genellikle kısa devrelere göre daha temizdir. Bunları kullanırsanız şunun farkında olun, fonksiyonunuz sadece `tanımsız` _(undefined)_ değerler için önceden tanımlanmış argümana kullanacaktır. `''`, `""`, `false`, `null`, `0`, ve `NaN` gibi "yanlış denilebilecek" değerler önceden tanımlanmış bir değerle değiştirilmez. +Default arguments are often cleaner than short circuiting. Be aware that if you +use them, your function will only provide default values for `undefined` +arguments. Other "falsy" values such as `''`, `""`, `false`, `null`, `0`, and +`NaN`, will not be replaced by a default value. -**Kötü:** +**Bad:** ```javascript function createMicrobrewery(name) { @@ -195,7 +217,7 @@ function createMicrobrewery(name) { } ``` -**İyi:** +**Good:** ```javascript function createMicrobrewery(name = "Hipster Brew Co.") { @@ -203,27 +225,41 @@ function createMicrobrewery(name = "Hipster Brew Co.") { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Fonksiyonlar** +## **Functions** -### Fonksiyonlar argümanları (Tercihen 2 veya daha az) +### Function arguments (2 or fewer ideally) -Fonksiyon parametrelerinin sayısını sınırlamak inanılmaz derecede önemlidir, çünkü fonksiyonunuzu test etmeyi kolaylaştırır. Üçten fazlasına sahip olmak, her bir argümanla tonlarca farklı vakayı test etmeniz gereken bir kombinasyonel patlamaya yol açar. +Limiting the amount of function parameters is incredibly important because it +makes testing your function easier. Having more than three leads to a +combinatorial explosion where you have to test tons of different cases with +each separate argument. -Bir veya iki argüman ideal durumdur ve mümkünse üç tanesinden kaçınılmalıdır. Bundan daha fazlası birleştirilmeldir. Genellikle, -ikiden fazla argüman sonra fonksiyonunuz çok işlem yapmaya çalışıyor. Olmadığı durumlarda, çoğu zaman daha üst düzey bir nesne argüman olarak yeterli olacaktır. +One or two arguments is the ideal case, and three should be avoided if possible. +Anything more than that should be consolidated. Usually, if you have +more than two arguments then your function is trying to do too much. In cases +where it's not, most of the time a higher-level object will suffice as an +argument. -JavaScript havada nesne yapmanıza olanak sağladığı için, bir çok sınıf yapısına gerek kalmadan, bir nesneyi birden fazla nesne kullanmadan kullanabilirsiniz. +Since JavaScript allows you to make objects on the fly, without a lot of class +boilerplate, you can use an object if you are finding yourself needing a +lot of arguments. -Fonksiyonun hangi özellikleri beklediğini netleştirmek için ES2015 / ES6 ayrıştırma sintaksını kullanabilirsiniz. Bunun birkaç avantajı vardır: +To make it obvious what properties the function expects, you can use the ES2015/ES6 +destructuring syntax. This has a few advantages: -1. Birisi fonksiyonun imzasına baktığında, hangi özelliklerin kullanıldığını hemen anlar.. -2. Adlandırılmış parametreleri simüle etmek için kullanılabilir. -3. Ayrıştırma işlemi ayrıca fonksiyona iletilen argüman nesnesinin belirtilen ilk değerlerini de klonlar. Bu, yan etkilerin önlenmesine yardımcı olabilir. Not: Argüman nesnelerinden ayrıştırılan nesneler ve diziler klonlanmaz! -4. Linters, sizi kullanılmayan değerler için uyarabilir bu da ayrıştırmadan imkansız olurdu. +1. When someone looks at the function signature, it's immediately clear what + properties are being used. +2. It can be used to simulate named parameters. +3. Destructuring also clones the specified primitive values of the argument + object passed into the function. This can help prevent side effects. Note: + objects and arrays that are destructured from the argument object are NOT + cloned. +4. Linters can warn you about unused properties, which would be impossible + without destructuring. -**Kötü:** +**Bad:** ```javascript function createMenu(title, body, buttonText, cancellable) { @@ -234,7 +270,7 @@ createMenu("Foo", "Bar", "Baz", true); ``` -**İyi:** +**Good:** ```javascript function createMenu({ title, body, buttonText, cancellable }) { @@ -249,13 +285,17 @@ createMenu({ }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksiyonlar bir şey yapmalı +### Functions should do one thing -Bu, yazılım mühendisliğinde açık ara en önemli kuraldır. Fonksiyonlar birden fazla şey yaptığında, birleştirmesi, test etmesi ve anlamdırılması daha zordur. Bir fonksiyonu yalnızca bir eyleme ayırabildiğinizde, kolayca yeniden düzenlenebilir ve kodunuz çok daha temiz okunur. Bu yazıdan başka bir şey almazsanız dahi sadece bununla birçok geliştiricinin önünde olacaksınız. +This is by far the most important rule in software engineering. When functions +do more than one thing, they are harder to compose, test, and reason about. +When you can isolate a function to just one action, it can be refactored +easily and your code will read much cleaner. If you take nothing else away from +this guide other than this, you'll be ahead of many developers. -**Kötü:** +**Bad:** ```javascript function emailClients(clients) { @@ -268,7 +308,7 @@ function emailClients(clients) { } ``` -**İyi:** +**Good:** ```javascript function emailActiveClients(clients) { @@ -281,11 +321,11 @@ function isActiveClient(client) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksiyon isimleri ne yaptıklarını anlatmalı +### Function names should say what they do -**Kötü:** +**Bad:** ```javascript function addToDate(date, month) { @@ -294,11 +334,11 @@ function addToDate(date, month) { const date = new Date(); -// Fonksiyonun adından ne eklendiğini söylemek zor +// It's hard to tell from the function name what is added addToDate(date, 1); ``` -**İyi:** +**Good:** ```javascript function addMonthToDate(month, date) { @@ -309,13 +349,15 @@ const date = new Date(); addMonthToDate(1, date); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksiyonlar soyutlaştırmadan sadece bir seviye uzak olmalıdır +### Functions should only be one level of abstraction -Birden fazla soyutlama seviyeniz olduğunda fonksiyonunuz genellikle çok fazla şey yapar. Fonksiyonların bölünmesi, yeniden kullanılabilirliği ve daha kolay test yapılmasını sağlayacak. +When you have more than one level of abstraction your function is usually +doing too much. Splitting up functions leads to reusability and easier +testing. -**Kötü:** +**Bad:** ```javascript function parseBetterJSAlternative(code) { @@ -342,7 +384,7 @@ function parseBetterJSAlternative(code) { } ``` -**İyi:** +**Good:** ```javascript function parseBetterJSAlternative(code) { @@ -379,19 +421,32 @@ function parse(tokens) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Tekrarlanan kodu sil +### Remove duplicate code -Tekrarlanan kodlardan kaçınmak için elinizden geleni yapın. Tekrarlanan kod kötü çünkü bazı mantığı değiştirmeniz gerekirse bir şeyi değiştirmek için birden fazla yer olduğu anlamına geliyor. +Do your absolute best to avoid duplicate code. Duplicate code is bad because it +means that there's more than one place to alter something if you need to change +some logic. -Bir restoran işlettiğinizi ve stoklarınızı takip ettiğinizi düşünün: tüm domates, soğan, sarımsak, baharat, vb. onlara. Yalnızca bir listeniz varsa, güncellenecek tek bir yer vardır! +Imagine if you run a restaurant and you keep track of your inventory: all your +tomatoes, onions, garlic, spices, etc. If you have multiple lists that +you keep this on, then all have to be updated when you serve a dish with +tomatoes in them. If you only have one list, there's only one place to update! -Çoğunlukla yinelenen kodunuz vardır, çünkü çoğu şeyi ortak paylaşsalar dahi çok küçük bir kaç farklılık vardır, ancak farklılıkları sizi aynı şeylerin çoğunu yapan iki veya daha fazla ayrı fonksiyona sahip olmaya zorlar. Tekrarlanan kodun kaldırılması, bu farklı şeyleri tek bir fonksiyon / modül / sınıfla işleyebilecek bir soyutlama oluşturmak anlamına gelir. +Oftentimes you have duplicate code because you have two or more slightly +different things, that share a lot in common, but their differences force you +to have two or more separate functions that do much of the same things. Removing +duplicate code means creating an abstraction that can handle this set of +different things with just one function/module/class. -Soyutlamayı doğru yapmak kritik öneme sahiptir, bu yüzden _Sınıflar_ bölümünde belirtilen SOLID ilkelerini izlemelisiniz. Kötü soyutlamalar yinelenen koddan daha kötü olabilir, bu yüzden dikkatli olun! Bunu söyledikten sonra, eğer iyi bir soyutlama yapabilirseniz, yapın! Kendinizi tekrarlamayın, aksi takdirde bir şeyi değiştirmek istediğinizde kendinizi birden fazla yeri güncellerken bulacaksınız. +Getting the abstraction right is critical, that's why you should follow the +SOLID principles laid out in the _Classes_ section. Bad abstractions can be +worse than duplicate code, so be careful! Having said this, if you can make +a good abstraction, do it! Don't repeat yourself, otherwise you'll find yourself +updating multiple places anytime you want to change one thing. -**Kötü:** +**Bad:** ```javascript function showDeveloperList(developers) { @@ -425,7 +480,7 @@ function showManagerList(managers) { } ``` -**İyi:** +**Good:** ```javascript function showEmployeeList(employees) { @@ -452,11 +507,11 @@ function showEmployeeList(employees) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Object.assign ile varsayılan nesneleri ayarlama +### Set default objects with Object.assign -**Kötü:** +**Bad:** ```javascript const menuConfig = { @@ -477,12 +532,12 @@ function createMenu(config) { createMenu(menuConfig); ``` -**İyi:** +**Good:** ```javascript const menuConfig = { title: "Order", - // Kullanıcı 'body' eklemedi + // User did not include 'body' key buttonText: "Send", cancellable: true }; @@ -498,20 +553,20 @@ function createMenu(config) { config ); - // config çıktısı şimdi : {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} + // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } createMenu(menuConfig); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksiyon parametrelerinde işaretleme kullanma +### Don't use flags as function parameters -İşaretlemeler fonksiyonunuzun birden fazla şey yaptığını gösterir. Fonkisyonlar sadece tek şey yapmalılar. Eğer aşağıdakine benzer değişiklere ve mantıksal operatorlere sahip fonksiyonunuz varsa fonksiyonlarınızı ayırın. +Flags tell your user that this function does more than one thing. Functions should do one thing. Split out your functions if they are following different code paths based on a boolean. -**Kötü:** +**Bad:** ```javascript function createFile(name, temp) { @@ -523,7 +578,7 @@ function createFile(name, temp) { } ``` -**İyi:** +**Good:** ```javascript function createFile(name) { @@ -535,21 +590,30 @@ function createTempFile(name) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yan Etkilerden Kaçının (Bölüm 1) +### Avoid Side Effects (part 1) -Bir fonksiyon, bir değeri alıp başka bir değer veya değer döndürmekten başka bir şey yaparsa yan etki üretir. Bir yan etki, bir dosyaya yazma, bazı global değişkeni değiştirme veya yanlışlıkla tüm paranızı bir yabancıya gönderme olabilir. +A function produces a side effect if it does anything other than take a value in +and return another value or values. A side effect could be writing to a file, +modifying some global variable, or accidentally wiring all your money to a +stranger. -Şimdi, zaman zaman bir programda yan etkilere sahip olmanız gerekir. Önceki örnekte olduğu gibi, bir dosyaya yazmanız gerekebilir. Yapmak istediğiniz, bunu yapacağınız yeri merkezileştirmektir. Birden fazla yazma işlemi yapan fonksiyonlar veya sınıflar yapmayın. Bunu yapan bir servisiniz olsun. Bir ve sadece bir. +Now, you do need to have side effects in a program on occasion. Like the previous +example, you might need to write to a file. What you want to do is to +centralize where you are doing this. Don't have several functions and classes +that write to a particular file. Have one service that does it. One and only one. -Buradaki ana nokta, herhangi bir yapıya sahip olmayan nesneler arasında durumu(state) paylaşmak, herhangi bir şeyle yazılabilen değiştirilebilir(mutable) veri türlerini kullanmak ve yan etkilerinizin nerede ortaya çıktığını merkezileştirmemek gibi yaygın tuzaklardan kaçınmaktır. Bunu yapabilirseniz, diğer programcıların büyük çoğunluğundan daha mutlu olacaksınız. +The main point is to avoid common pitfalls like sharing state between objects +without any structure, using mutable data types that can be written to by anything, +and not centralizing where your side effects occur. If you can do this, you will +be happier than the vast majority of other programmers. -**Kötü:** +**Bad:** ```javascript -// Aşağıdaki fonksiyon Global değişkeni refere alıyor -// Bu adı kullanan başka bir fonksiyonumuz olsaydı, şimdi bir dizi olurdu ve onu bozacaktı. +// Global variable referenced by following function. +// If we had another function that used this name, now it'd be an array and it could break it. let name = "Ryan McDermott"; function splitIntoFirstAndLastName() { @@ -561,7 +625,7 @@ splitIntoFirstAndLastName(); console.log(name); // ['Ryan', 'McDermott']; ``` -**İyi:** +**Good:** ```javascript function splitIntoFirstAndLastName(name) { @@ -575,27 +639,44 @@ console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott']; ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yan Etkilerden Kaçının (Bölüm 2) +### Avoid Side Effects (part 2) -JavaScript'te, temel öğeler değerlerle aktarılır (passed by value) ve objeler/diziler referans ile aktarılır (passed by reference). +In JavaScript, primitives are passed by value and objects/arrays are passed by +reference. In the case of objects and arrays, if your function makes a change +in a shopping cart array, for example, by adding an item to purchase, +then any other function that uses that `cart` array will be affected by this +addition. That may be great, however it can be bad too. Let's imagine a bad +situation: -Bu durumda, nesnelerde ve dizilerde fonksiyonunuz bir değişiklik yaparsa -örneğin, bir alışveriş sepeti dizisinde, satın almak için bir öğe ekleyerek, -bu `cart` dizisini kullanan diğer fonksiyonlar bu eklemeden etkilenecektir. -Bu harika olabilir, ancak kötü de olabilir. Kötü bir hayal edelim -durum: +The user clicks the "Purchase" button which calls a `purchase` function that +spawns a network request and sends the `cart` array to the server. Because +of a bad network connection, the `purchase` function has to keep retrying the +request. Now, what if in the meantime the user accidentally clicks "Add to Cart" +button on an item they don't actually want before the network request begins? +If that happens and the network request begins, then that purchase function +will send the accidentally added item because it has a reference to a shopping +cart array that the `addItemToCart` function modified by adding an unwanted +item. -Kullanıcı, 'Satın Al' butonuna basar ve bu `satınal` fonksiyonu sunucuya bir istek atarak `sepet` dizisini sunucuya gönderir. Kötü bir ağ bağlantısı nedeniyle, `satınal` işlevi isteği yeniden denemeye devam etmelidir. Şimdi, bu arada kullanıcı yanlışlıkla ağ isteği başlamadan istemedikleri bir öğenin üzerine "Sepete Ekle" düğmesini tıklarsa ne olur? Bu olursa ve ağ isteği başlarsa, yanlışlıkla satın alınan öğeyi gönderir çünkü alışveriş sepeti dizisine, `ürünüSepeteEkle` işlevinin istenmeyen bir öğe ekleyerek değiştirdiği bir referansı vardır. `ürünüSepeteEkle` ın her zaman `sepeti` klonlaması, düzenlemesi ve klonu döndürmesi için harika bir çözüm olacaktır. Bu, alışveriş sepetinin referansını tutan başka hiçbir işlevin herhangi bir değişiklikten etkilenmemesini sağlar. +A great solution would be for the `addItemToCart` to always clone the `cart`, +edit it, and return the clone. This ensures that no other functions that are +holding onto a reference of the shopping cart will be affected by any changes. -Bu yaklaşıma değinecek iki uyarı: +Two caveats to mention to this approach: -1. Girilen nesnesini gerçekten değiştirmek istediğiniz durumlar olabilir, ancak bunu uyguladığınızda, bu vakaların oldukça nadir olduğunu göreceksiniz. Çoğu şeyin yan etkisi olmayacak şekilde yeniden düzenlenebilir! +1. There might be cases where you actually want to modify the input object, + but when you adopt this programming practice you will find that those cases + are pretty rare. Most things can be refactored to have no side effects! -2. Büyük nesneleri klonlamak performans açısından çok pahalı olabilir. Neyse ki, bu pratikte büyük bir sorun değildir, çünkü bu tür programlama yaklaşımlarını manuel yapmaktansa daha hızlı olmasını ve büyük nesneleri ve dizileri klonlanlarken daha az bellek harcayan [harika kütüphaneler](https://facebook.github.io/immutable-js/) vardır. +2. Cloning big objects can be very expensive in terms of performance. Luckily, + this isn't a big issue in practice because there are + [great libraries](https://facebook.github.io/immutable-js/) that allow + this kind of programming approach to be fast and not as memory intensive as + it would be for you to manually clone objects and arrays. -**Kötü:** +**Bad:** ```javascript const addItemToCart = (cart, item) => { @@ -603,7 +684,7 @@ const addItemToCart = (cart, item) => { }; ``` -**İyi:** +**Good:** ```javascript const addItemToCart = (cart, item) => { @@ -611,17 +692,21 @@ const addItemToCart = (cart, item) => { }; ``` -**[⬆ Başa dön](#İçindekiler)** - -### Global fonksiyonlar yazma +**[⬆ back to top](#table-of-contents)** -Globalleri kirletmek JavaScript'te kötü bir uygulamadır, çünkü başka bir kütüphaneyle çakıştırabilirsiniz ve API'lerinizi kullananlar kişiler canlıya çıkana kadar bu aksi durumların farkında olmayabilir. +### Don't write to global functions -Bir örnek düşünelim: JavaScript'in yerel kütüphanesindeki dizi `diff` methodunu genişletmek ve iki dizinin farklılıklarını göstermek istediğinizi var sayalım. JavaScript'in yerel Array yöntemini iki dizi arasındaki farkı gösterebilecek bir "diff" yöntemine genişletmek mi istiyorsunuz? +Polluting globals is a bad practice in JavaScript because you could clash with another +library and the user of your API would be none-the-wiser until they get an +exception in production. Let's think about an example: what if you wanted to +extend JavaScript's native Array method to have a `diff` method that could +show the difference between two arrays? You could write your new function +to the `Array.prototype`, but it could clash with another library that tried +to do the same thing. What if that other library was just using `diff` to find +the difference between the first and last elements of an array? This is why it +would be much better to just use ES2015/ES6 classes and simply extend the `Array` global. -Yeni fonksiyonunuzu `Array.prototype`'e yazabilirsiniz, ancak aynı şeyi yapmaya çalışan başka bir kütüphane ile çakışabilir. Ya diğer kütüphane bir dizinin ilk ve son elemanları arasındaki farkı bulmak için sadece `diff` kullanıyorsa? Bu yüzden sadece ES2015 / ES6 sınıflarını kullanmak ve `Array` globalini genişletmek çok daha iyi olurdu. - -**Kötü:** +**Bad:** ```javascript Array.prototype.diff = function diff(comparisonArray) { @@ -630,7 +715,7 @@ Array.prototype.diff = function diff(comparisonArray) { }; ``` -**İyi:** +**Good:** ```javascript class SuperArray extends Array { @@ -641,13 +726,15 @@ class SuperArray extends Array { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Zorunlu programlama yerine fonksiyonel programlamayı tercih edin +### Favor functional programming over imperative programming -JavaScript, Haskell'in olduğu gibi işlevsel bir dil değildir, ancak işlevsel bir tadı vardır. İşlevsel diller daha temiz ve test edilmesi daha kolay olabilir. Yapabildiğinizde bu tarz bir programlama yapın. +JavaScript isn't a functional language in the way that Haskell is, but it has +a functional flavor to it. Functional languages can be cleaner and easier to test. +Favor this style of programming when you can. -**Kötü:** +**Bad:** ```javascript const programmerOutput = [ @@ -676,7 +763,7 @@ for (let i = 0; i < programmerOutput.length; i++) { } ``` -**İyi:** +**Good:** ```javascript const programmerOutput = [ @@ -704,11 +791,11 @@ const totalOutput = programmerOutput.reduce( ); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Koşulları kapsamak +### Encapsulate conditionals -**Kötü:** +**Bad:** ```javascript if (fsm.state === "fetching" && isEmpty(listNode)) { @@ -716,7 +803,7 @@ if (fsm.state === "fetching" && isEmpty(listNode)) { } ``` -**İyi:** +**Good:** ```javascript function shouldShowSpinner(fsm, listNode) { @@ -728,11 +815,11 @@ if (shouldShowSpinner(fsmInstance, listNodeInstance)) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** ### Avoid negative conditionals -**Kötü:** +**Bad:** ```javascript function isDOMNodeNotPresent(node) { @@ -744,7 +831,7 @@ if (!isDOMNodeNotPresent(node)) { } ``` -**İyi:** +**Good:** ```javascript function isDOMNodePresent(node) { @@ -756,14 +843,20 @@ if (isDOMNodePresent(node)) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Koşullardan kaçının +### Avoid conditionals -Bu imkansız bir görev gibi görünüyor. Bunu ilk kez duyduktan sonra, çoğu kişi "`if` ifadesi olmadan nasıl bir şey yapmam gerekiyor?" Cevap şu ki -birçok durumda aynı görevi yerine getirmek için polimorfizm kullanabilirsiniz. İkinci soru genellikle, "peki bu harika ama neden bunu yapmak isteyeyim ki?" Cevap, daha önce öğrendiğimiz temiz bir kod kavramıydı: bir fonksiyon sadece bir şey yapmalı. `If` ifadeleri olan sınıflarınız ve fonksiyonlarınız olduğunda, kullanıcılara işlevinizin birden fazla şey yaptığını söylüyor. Unutmayın, sadece bir şey yapın. +This seems like an impossible task. Upon first hearing this, most people say, +"how am I supposed to do anything without an `if` statement?" The answer is that +you can use polymorphism to achieve the same task in many cases. The second +question is usually, "well that's great but why would I want to do that?" The +answer is a previous clean code concept we learned: a function should only do +one thing. When you have classes and functions that have `if` statements, you +are telling your user that your function does more than one thing. Remember, +just do one thing. -**Kötü:** +**Bad:** ```javascript class Airplane { @@ -781,7 +874,7 @@ class Airplane { } ``` -**İyi:** +**Good:** ```javascript class Airplane { @@ -810,13 +903,16 @@ class Cessna extends Airplane { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yazım denetiminden kaçının (Bölüm 1) +### Avoid type-checking (part 1) -JavaScript türsüzdür, yani işlevleriniz her türlü argümanı alabilir. Bazen bu özgürlük bizi oltaya getirebilir ve fonksiyonlarınızda tip kontrolü yapmak cazip hale gelir. Bunu yapmaktan kaçınmanın birçok yolu vardır. Dikkate alınması gereken ilk şey tutarlı API'lardır. +JavaScript is untyped, which means your functions can take any type of argument. +Sometimes you are bitten by this freedom and it becomes tempting to do +type-checking in your functions. There are many ways to avoid having to do this. +The first thing to consider is consistent APIs. -**Kötü:** +**Bad:** ```javascript function travelToTexas(vehicle) { @@ -828,7 +924,7 @@ function travelToTexas(vehicle) { } ``` -**İyi:** +**Good:** ```javascript function travelToTexas(vehicle) { @@ -836,14 +932,21 @@ function travelToTexas(vehicle) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yazım denetiminden kaçının (Bölüm 2) +### Avoid type-checking (part 2) -Dizeler ve tamsayılar gibi temel ilkel değerlerle çalışıyorsanız, -ve polimorfizm kullanamazsınız, ancak yine de yazım denetimi yapma gereğini hissediyorsanız, TypeScript kullanmayı düşünmelisiniz. Standart JavaScript sentaks üstünde statik yazım sağladığı için normal JavaScript'e mükemmel bir alternatiftir. Manuel olarak normal JavaScript'i kontrol etmeyle ilgili sorun, iyi yapmak o kadar fazla ayrıntılı gerektirir ki, elde ettiğiniz sahte "tip güvenliği" kaybettiğiniz okunabilirliği telafi etmez. JavaScript'inizi temiz tutun, iyi testler yazın ve iyi kod incelemelerine sahip olun. Aksi takdirde, hepsini TypeScript ile yapın (dediğim gibi harika bir alternatif!). +If you are working with basic primitive values like strings and integers, +and you can't use polymorphism but you still feel the need to type-check, +you should consider using TypeScript. It is an excellent alternative to normal +JavaScript, as it provides you with static typing on top of standard JavaScript +syntax. The problem with manually type-checking normal JavaScript is that +doing it well requires so much extra verbiage that the faux "type-safety" you get +doesn't make up for the lost readability. Keep your JavaScript clean, write +good tests, and have good code reviews. Otherwise, do all of that but with +TypeScript (which, like I said, is a great alternative!). -**Kötü:** +**Bad:** ```javascript function combine(val1, val2) { @@ -858,7 +961,7 @@ function combine(val1, val2) { } ``` -**İyi:** +**Good:** ```javascript function combine(val1, val2) { @@ -866,25 +969,27 @@ function combine(val1, val2) { } ``` -**[⬆ Başa dön](#İçindekiler)** - -### Aşırı optimizasyon yapma +**[⬆ back to top](#table-of-contents)** -Modern tarayıcılar çalışma zamanında çok sayıda optimizasyon yapar. Çoğu zaman, eğer optimize ediyorsanız, sadece zamanınızı boşa harcıyorsunuz demektir. +### Don't over-optimize -Optimizasyonun nerede olmadığını görmek için [iyi kaynaklar](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) vardır. Bunları optimize edene kadar işaretleyebilirsiniz. +Modern browsers do a lot of optimization under-the-hood at runtime. A lot of +times, if you are optimizing then you are just wasting your time. [There are good +resources](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) +for seeing where optimization is lacking. Target those in the meantime, until +they are fixed if they can be. -**Kötü:** +**Bad:** ```javascript -// Eski tarayıcılarda, önbelleğe alınmamış "list.length" içeren her yineleme maliyetli olacaktır -// list.length yeniden hesaplanması nedeniyle. Modern tarayıcılarda bu optimize edilmiştir. +// On old browsers, each iteration with uncached `list.length` would be costly +// because of `list.length` recomputation. In modern browsers, this is optimized. for (let i = 0, len = list.length; i < len; i++) { // ... } ``` -**İyi:** +**Good:** ```javascript for (let i = 0; i < list.length; i++) { @@ -892,13 +997,15 @@ for (let i = 0; i < list.length; i++) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Kullanılmayan kodları silin +### Remove dead code -Ölü kod, yinelenen kod kadar kötü. Kod tabanınızda tutmak için bir neden yoktur. Eğer çağrılmazsa, ondan kurtulun! Hala ihtiyacınız varsa sürüm geçmişinizde güvende olacaktır. +Dead code is just as bad as duplicate code. There's no reason to keep it in +your codebase. If it's not being called, get rid of it! It will still be safe +in your version history if you still need it. -**Kötü:** +**Bad:** ```javascript function oldRequestModule(url) { @@ -913,7 +1020,7 @@ const req = newRequestModule; inventoryTracker("apples", req, "www.inventory-awesome.io"); ``` -**İyi:** +**Good:** ```javascript function newRequestModule(url) { @@ -924,21 +1031,25 @@ const req = newRequestModule; inventoryTracker("apples", req, "www.inventory-awesome.io"); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Nesneler ve Veri Yapıları** +## **Objects and Data Structures** -### Alıcıları ve ayarlayıcıları kullanma (Getters & Setters) +### Use getters and setters -Nesnelerdeki verilere erişmek için alıcıları ve ayarlayıcıları kullanmak, bir nesnedeki bir özelliği aramaktan daha iyi olabilir. "Neden?" sorabilirsiniz. Pekala, işte organize edilmeden nedenlerin bir listesi: +Using getters and setters to access data on objects could be better than simply +looking for a property on an object. "Why?" you might ask. Well, here's an +unorganized list of reasons why: -- Bir nesne özelliği almanın ötesinde daha fazlasını yapmak istediğinizde, kod tabanınızdaki her erişimciye bakmanız ve değiştirmeniz gerekmez. -- `set`yaparken doğrulama basitçe yapılabilir. -- Dahili gösterimi içine alır. -- Alma ve ayarlama sırasında kayıtlamayı(logging) ve hata yönetimi(error handling) eklemek kolaydır. -- Diyelimki sunucudan alıyorsunuz, nesnenizin özelliklerini tembel(lazy load) olarak yükleyebilirsiniz. +- When you want to do more beyond getting an object property, you don't have + to look up and change every accessor in your codebase. +- Makes adding validation simple when doing a `set`. +- Encapsulates the internal representation. +- Easy to add logging and error handling when getting and setting. +- You can lazy load your object's properties, let's say getting it from a + server. -**Kötü:** +**Bad:** ```javascript function makeBankAccount() { @@ -954,19 +1065,19 @@ const account = makeBankAccount(); account.balance = 100; ``` -**İyi:** +**Good:** ```javascript function makeBankAccount() { - // Bu fonksiyon özelinde (private) + // this one is private let balance = 0; - // "alıcı"yı, genel(public) objeyi döndürerek yap + // a "getter", made public via the returned object below function getBalance() { return balance; } - - // "ayarlayıcı"yı, genel(public) objeyi döndürerek yap + + // a "setter", made public via the returned object below function setBalance(amount) { // ... validate before updating the balance balance = amount; @@ -983,13 +1094,13 @@ const account = makeBankAccount(); account.setBalance(100); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Nesnelerin özel üyeleri olmasını sağlama +### Make objects have private members This can be accomplished through closures (for ES5 and below). -**Kötü:** +**Bad:** ```javascript const Employee = function(name) { @@ -1006,7 +1117,7 @@ delete employee.name; console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined ``` -**İyi:** +**Good:** ```javascript function makeEmployee(name) { @@ -1023,15 +1134,18 @@ delete employee.name; console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Sınıflar** +## **Classes** -### ES5 düz fonksiyonlar yerine ES2015 / ES6 sınıflarını tercih et +### Prefer ES2015/ES6 classes over ES5 plain functions -Klasik ES5 sınıfları için okunabilir sınıf mirası, yapısı ve yöntem tanımları almak çok zordur. Miras almaya(inheritance) ihtiyacınız varsa (ve gerekmeyebileceğini unutmayın), ES2015 / ES6 sınıflarını tercih edin. Bununla birlikte, kendinizi daha büyük ve daha karmaşık nesnelere ihtiyaç duyana kadar küçük işlevlere tercih edin. +It's very difficult to get readable class inheritance, construction, and method +definitions for classical ES5 classes. If you need inheritance (and be aware +that you might not), then prefer ES2015/ES6 classes. However, prefer small functions over +classes until you find yourself needing larger and more complex objects. -**Kötü:** +**Bad:** ```javascript const Animal = function(age) { @@ -1071,7 +1185,7 @@ Human.prototype.constructor = Human; Human.prototype.speak = function speak() {}; ``` -**İyi:** +**Good:** ```javascript class Animal { @@ -1107,13 +1221,17 @@ class Human extends Mammal { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yöntem zincirini kullan +### Use method chaining -Bu desen JavaScript'te çok kullanışlıdır ve jQuery ve Lodash gibi birçok kütüphanede görürsünüz. Kodunuzun etkileyici ve daha az detaylı olmasını sağlar. Bu nedenle, diyorum ki, yöntem zincirleme kullanın ve kodunuzun ne kadar temiz olacağını göreceksiniz. Sınıf fonksiyonlarınızda, her fonksiyonun sonunda `this`'i döndürmeniz yeterlidir ve daha fazla sınıf yöntemini buna zincirleyebilirsiniz. +This pattern is very useful in JavaScript and you see it in many libraries such +as jQuery and Lodash. It allows your code to be expressive, and less verbose. +For that reason, I say, use method chaining and take a look at how clean your code +will be. In your class functions, simply return `this` at the end of every function, +and you can chain further class methods onto it. -**Kötü:** +**Bad:** ```javascript class Car { @@ -1145,7 +1263,7 @@ car.setColor("pink"); car.save(); ``` -**İyi:** +**Good:** ```javascript class Car { @@ -1157,25 +1275,25 @@ class Car { setMake(make) { this.make = make; - // NOT: Zincirleme için `this` döndür + // NOTE: Returning this for chaining return this; } setModel(model) { this.model = model; - // NOT: Zincirleme için `this` döndür + // NOTE: Returning this for chaining return this; } setColor(color) { this.color = color; - // NOT: Zincirleme için `this` döndür + // NOTE: Returning this for chaining return this; } save() { console.log(this.make, this.model, this.color); - // NOT: Zincirleme için `this` döndür + // NOTE: Returning this for chaining return this; } } @@ -1183,19 +1301,28 @@ class Car { const car = new Car("Ford", "F-150", "red").setColor("pink").save(); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Miras yerine kompozisyon tercih et +### Prefer composition over inheritance -Dörtlü çete tarafından başlatılan ünlü [_Tasarım Desenleri_](https://en.wikipedia.org/wiki/Design_Patterns) gibi, siz de kompozisyonu, miras bırakmaya yerine göre tercih etmelisiniz. Miras kullanmak için birçok iyi neden ve kompozisyon kullanmak için birçok iyi neden vardır. Bu maksimum nokta için ana nokta, zihniniz içgüdüsel olarak miras kullanma için giderse, kompozisyon sorununuzu daha iyi modelleyip değiştiremeyeceğini düşünmeye çalışın. Bazı durumlarda olabilir. +As stated famously in [_Design Patterns_](https://en.wikipedia.org/wiki/Design_Patterns) by the Gang of Four, +you should prefer composition over inheritance where you can. There are lots of +good reasons to use inheritance and lots of good reasons to use composition. +The main point for this maxim is that if your mind instinctively goes for +inheritance, try to think if composition could model your problem better. In some +cases it can. -O zaman "ne zaman miras kullanmalıyım?" diye merak ediyor olabilirsiniz. O eldeki probleminize bağlıdır, ancak bu mirasın kompozisyondan daha mantıklı olduğu iyi bir listedir: +You might be wondering then, "when should I use inheritance?" It +depends on your problem at hand, but this is a decent list of when inheritance +makes more sense than composition: -1. Mirasınız "has-a" değil, "is-a" ilişkisini temsil eder ilişki (İnsan-> Hayvan ve Kullanıcı-> KullanıcıAyrıntıları). -2. Temel sınıflardan kodu yeniden kullanabilirsiniz (İnsanlar tüm hayvanlar gibi hareket edebilir). -3. Temel sınıfı değiştirerek türetilmiş sınıflarda genel değişiklikler yapmak istiyorsunuz. (Hareket ettiklerinde tüm hayvanların kalori harcamalarını değiştirin). +1. Your inheritance represents an "is-a" relationship and not a "has-a" + relationship (Human->Animal vs. User->UserDetails). +2. You can reuse code from the base classes (Humans can move like all animals). +3. You want to make global changes to derived classes by changing a base class. + (Change the caloric expenditure of all animals when they move). -**Kötü:** +**Bad:** ```javascript class Employee { @@ -1207,7 +1334,7 @@ class Employee { // ... } -// Kötü çünkü Çalışanların(Employees) vergi bilgisi 'var'. ÇalışanVergiBilgisi(EmployeeTaxData) bir çeşit Çalışan(Employee) değil. +// Bad because Employees "have" tax data. EmployeeTaxData is not a type of Employee class EmployeeTaxData extends Employee { constructor(ssn, salary) { super(); @@ -1219,7 +1346,7 @@ class EmployeeTaxData extends Employee { } ``` -**İyi:** +**Good:** ```javascript class EmployeeTaxData { @@ -1244,15 +1371,22 @@ class Employee { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** ## **SOLID** -### Tek Sorumluluk İlkesi (SRP) +### Single Responsibility Principle (SRP) -Temiz Kod'da belirtildiği gibi, "Bir sınıfın değişmesi için asla birden fazla sebep olmamalıdır". Bir sınıfı tıklım tıklım bir çok işlevsellikle doldurmak çekici gelebilir, tıpkı uçuşlarda yanına alabileceğiniz bir valiz gibi. Bununla ilgili sorun, sınıfınızın kavramsal olarak uyumlu olmayacağı ve değişmesi için birçok neden vereceği yönündedir. Bir sınıfı değiştirmek için ihtiyaç duyduğunuz sayıyı en aza indirmek önemlidir. Bir sınıfta çok fazla işlevsellik varsa ve bir parçasını değiştirirseniz, bunun kod tabanınızdaki diğer bağımlı modülleri nasıl etkileyeceğini anlamak zor olabilir. +As stated in Clean Code, "There should never be more than one reason for a class +to change". It's tempting to jam-pack a class with a lot of functionality, like +when you can only take one suitcase on your flight. The issue with this is +that your class won't be conceptually cohesive and it will give it many reasons +to change. Minimizing the amount of times you need to change a class is important. +It's important because if too much functionality is in one class and you modify +a piece of it, it can be difficult to understand how that will affect other +dependent modules in your codebase. -**Kötü:** +**Bad:** ```javascript class UserSettings { @@ -1272,7 +1406,7 @@ class UserSettings { } ``` -**İyi:** +**Good:** ```javascript class UserAuth { @@ -1299,13 +1433,16 @@ class UserSettings { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Açık / Kapalı Prensibi (OCP) +### Open/Closed Principle (OCP) -Bertrand Meyer tarafından belirtildiği gibi, "yazılım varlıkları (sınıflar, modüller, işlevler, vb.) Genişletme için açık, ancak değişiklik için kapalı olmalıdır." Bu ne anlama geliyor? Bu ilke, temel olarak kullanıcıların mevcut kodu değiştirmeden yeni işlevler eklemelerine izin vermeniz gerektiğini belirtir. +As stated by Bertrand Meyer, "software entities (classes, modules, functions, +etc.) should be open for extension, but closed for modification." What does that +mean though? This principle basically states that you should allow users to +add new functionalities without changing existing code. -**Kötü:** +**Bad:** ```javascript class AjaxAdapter extends Adapter { @@ -1349,7 +1486,7 @@ function makeHttpCall(url) { } ``` -**İyi:** +**Good:** ```javascript class AjaxAdapter extends Adapter { @@ -1387,15 +1524,24 @@ class HttpRequester { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Liskov’un Yerine Geçme Prensibi (LSP) +### Liskov Substitution Principle (LSP) -Bu çok basit bir kavram için korkutucu bir terimdir.Resmi olarak "S, T'nin bir alt tipiyse, o zaman T tipi nesnelerin yerine S tipi nesneler (yani, S tipi nesneler T programındaki nesnelerin yerine geçebilir), bu programın istenen özelliklerini değiştirmeden değiştirilebilir (doğruluk, yapılan görev vb.) " Bu daha da korkunç bir tanım. +This is a scary term for a very simple concept. It's formally defined as "If S +is a subtype of T, then objects of type T may be replaced with objects of type S +(i.e., objects of type S may substitute objects of type T) without altering any +of the desirable properties of that program (correctness, task performed, +etc.)." That's an even scarier definition. -Bunun için en iyi açıklama, bir üst sınıfınız ve bir alt sınıfınız varsa, temel sınıf ve alt sınıf yanlış sonuçlar elde etmeden birbirinin yerine kullanılabilir.Bu hala kafa karıştırıcı olabilir, bu yüzden klasik Kare Dikdörtgen örneğine bakalım. Matematiksel olarak, bir kare bir dikdörtgendir, ancak miras yoluyla "is-a" ilişkisini kullanarak model verirseniz, hızlı bir şekilde sorun yaşarsınız. +The best explanation for this is if you have a parent class and a child class, +then the base class and child class can be used interchangeably without getting +incorrect results. This might still be confusing, so let's take a look at the +classic Square-Rectangle example. Mathematically, a square is a rectangle, but +if you model it using the "is-a" relationship via inheritance, you quickly +get into trouble. -**Kötü:** +**Bad:** ```javascript class Rectangle { @@ -1441,7 +1587,7 @@ function renderLargeRectangles(rectangles) { rectangles.forEach(rectangle => { rectangle.setWidth(4); rectangle.setHeight(5); - const area = rectangle.getArea(); // KÖTÜ: Kare için 25 değerini döndürür. 20 olmalı. + const area = rectangle.getArea(); // BAD: Returns 25 for Square. Should be 20. rectangle.render(area); }); } @@ -1450,7 +1596,7 @@ const rectangles = [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles(rectangles); ``` -**İyi:** +**Good:** ```javascript class Shape { @@ -1497,17 +1643,25 @@ const shapes = [new Rectangle(4, 5), new Rectangle(4, 5), new Square(5)]; renderLargeShapes(shapes); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Arayüzlerin Ayrımı Prensibi (ISP) +### Interface Segregation Principle (ISP) -JavaScript'in arayüzleri yoktur, bu nedenle bu ilke diğerleri kadar kesin olarak geçerli değildir. Bununla birlikte, JavaScript'in tür sistemi eksikliğinde bile önemli ve alâkalıdır. +JavaScript doesn't have interfaces so this principle doesn't apply as strictly +as others. However, it's important and relevant even with JavaScript's lack of +type system. -ISP, "kullanıcılar kullanmadığı arabirimlere bağımlı olmaya zorlanmamalıdır." der. Arabirimler, `Duck Typing` yüzünden JavaScript'de üstü kapalı anlaşmalardır. +ISP states that "Clients should not be forced to depend upon interfaces that +they do not use." Interfaces are implicit contracts in JavaScript because of +duck typing. -Bu ilkeyi JavaScript'te gösteren iyi bir örnek, sınıflar büyük ayar nesneleri gerektirir. Kullanıcıların büyük miktarda seçenek ayarlamalarını istememek gerekli değildir, çünkü çoğu zaman tüm ayarlara ihtiyaç duymazlar. Bunları isteğe bağlı yapmak, bir "büyük arayüzü" olmasını önlemeye yardımcı olur. +A good example to look at that demonstrates this principle in JavaScript is for +classes that require large settings objects. Not requiring clients to setup +huge amounts of options is beneficial, because most of the time they won't need +all of the settings. Making them optional helps prevent having a +"fat interface". -**Kötü:** +**Bad:** ```javascript class DOMTraverser { @@ -1528,12 +1682,12 @@ class DOMTraverser { const $ = new DOMTraverser({ rootNode: document.getElementsByTagName("body"), - animationModule() {} // Coğunlukla, bunu canlandırmamız gerekmeyecek + animationModule() {} // Most of the time, we won't need to animate when traversing. // ... }); ``` -**İyi:** +**Good:** ```javascript class DOMTraverser { @@ -1567,24 +1721,32 @@ const $ = new DOMTraverser({ }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Bağlılığı Tersine Çevirme Prensibi (DIP) +### Dependency Inversion Principle (DIP) -Bu ilke iki temel şeyi ifade eder: +This principle states two essential things: -1. Yüksek seviyeli modüller, düşük seviyeli modüllere bağlı olmamalıdır. Her ikisi de soyutlamalara bağlı olmalıdır. -2. Soyutlamalar detaylara bağlı olmamalıdır. Ayrıntılar soyutlamalara bağlı olmalıdır. +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. -İlk başta bunu anlamak zor olabilir, ancak AngularJS ile çalıştıysanız, bu prensibin Bağımlılık Enjeksiyonu (DI) şeklinde bir uygulamasını gördünüz. Aynı kavramlar olmasalar da, DIP yüksek seviyede modüllerin düşük seviyeli modüllerinin detaylarını bilmelerini ve ayarlamalarını sağlar. -Bunu DI ile başarabilir. Bunun büyük bir yararı, modüller arasındaki bağlantıyı azaltmasıdır. Eşleştirme(Coupling) çok kötü bir gelişme modelidir çünkü -kodunuzu yeniden düzenleme zorlaştırır. +This can be hard to understand at first, but if you've worked with AngularJS, +you've seen an implementation of this principle in the form of Dependency +Injection (DI). While they are not identical concepts, DIP keeps high-level +modules from knowing the details of its low-level modules and setting them up. +It can accomplish this through DI. A huge benefit of this is that it reduces +the coupling between modules. Coupling is a very bad development pattern because +it makes your code hard to refactor. -Daha önce belirtildiği gibi, JavaScript'in arayüzleri yoktur, bu nedenle soyutlamalar örtük sözleşmelere bağlıdır. -Yani, bir nesnenin / sınıfın başka bir nesneye / sınıfa maruz bıraktığı yöntemler ve özellikler. -Aşağıdaki örnekte, örtük sözleşme, bir `InventoryTracker` için herhangi bir Request modülünün `requestItems` yöntemine sahip olacağıdır. +As stated previously, JavaScript doesn't have interfaces so the abstractions +that are depended upon are implicit contracts. That is to say, the methods +and properties that an object/class exposes to another object/class. In the +example below, the implicit contract is that any Request module for an +`InventoryTracker` will have a `requestItems` method. -**Kötü:** +**Bad:** ```javascript class InventoryRequester { @@ -1601,8 +1763,8 @@ class InventoryTracker { constructor(items) { this.items = items; - // KÖTÜ: Belirli bir istek uygulamasına bağımlılık yarattık. -    // requestItems sadece `request` 'e bağlımlı olmalıdır. + // BAD: We have created a dependency on a specific request implementation. + // We should just have requestItems depend on a request method: `request` this.requester = new InventoryRequester(); } @@ -1617,7 +1779,7 @@ const inventoryTracker = new InventoryTracker(["apples", "bananas"]); inventoryTracker.requestItems(); ``` -**İyi:** +**Good:** ```javascript class InventoryTracker { @@ -1653,8 +1815,8 @@ class InventoryRequesterV2 { } } -// Bağımlılıklarımızı harici olarak yapılandırarak ve enjekte ederek -// istek modülümüzü WebSockets kullanan yeni ve havalı bir modülle kolayca değiştirebiliriz. +// By constructing our dependencies externally and injecting them, we can easily +// substitute our request module for a fancy new one that uses WebSockets. const inventoryTracker = new InventoryTracker( ["apples", "bananas"], new InventoryRequesterV2() @@ -1662,19 +1824,28 @@ const inventoryTracker = new InventoryTracker( inventoryTracker.requestItems(); ``` -**[⬆ Başa dön](#İçindekiler)** - -## **Testler** +**[⬆ back to top](#table-of-contents)** -Test etmek canlıya çıkmaktan bile önemlidir. Eğer testiniz yoksa veya yetersiz bir miktardaysa, kodu her gönderdiğinizde hiçbir şeyin bozulmadığına emin olmazsınız. Neyin yeterli bir miktar oluşturduğuna karar vermek takımınıza bağlıdır, %100 kapsama sahip olmak (tüm ifadeler ve şubeler) size güven ve gönül rahatlığı sağlar. Bu, harika bir test framework'üne sahip olmanın yanı sıra, [iyi bir kapsama aracı](https://gotwarlost.github.io/istanbul/) kullanmanız gerektiği anlamına gelir +## **Testing** -Test yazmamanın mazereti yoktur. Çok sayıda [iyi JS test framework'ü](https://jstherightway.org/#testing-tools) vardır, bu yüzden ekibinize uyan birini bulun. +Testing is more important than shipping. If you have no tests or an +inadequate amount, then every time you ship code you won't be sure that you +didn't break anything. Deciding on what constitutes an adequate amount is up +to your team, but having 100% coverage (all statements and branches) is how +you achieve very high confidence and developer peace of mind. This means that +in addition to having a great testing framework, you also need to use a +[good coverage tool](https://gotwarlost.github.io/istanbul/). -Ekibiniz için uygun olanı bulduğunuzda, kullanılan her yeni özellik / modül için daima testler yazmayı hedefleyin. Tercih ettiğiniz yöntem Test Odaklı Geliştirme (TDD) ise, bu harika, ancak asıl mesele, herhangi bir özelliği başlatmadan veya mevcut bir özelliği yeniden düzenlemeden önce kapsama hedeflerinize ulaştığınızdan emin olmaktır. +There's no excuse to not write tests. There are [plenty of good JS test frameworks](https://jstherightway.org/#testing-tools), so find one that your team prefers. +When you find one that works for your team, then aim to always write tests +for every new feature/module you introduce. If your preferred method is +Test Driven Development (TDD), that is great, but the main point is to just +make sure you are reaching your coverage goals before launching any feature, +or refactoring an existing one. -### Her test için tek konsept +### Single concept per test -**Kötü:** +**Bad:** ```javascript import assert from "assert"; @@ -1698,7 +1869,7 @@ describe("MomentJS", () => { }); ``` -**İyi:** +**Good:** ```javascript import assert from "assert"; @@ -1724,15 +1895,16 @@ describe("MomentJS", () => { }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Tutarlılık** +## **Concurrency** -### Promises kullanın, callback değil +### Use Promises, not callbacks -'Callback'ler temiz değildir ve aşırı miktarda iç içe geçmeye neden olurlar. ES2015 / ES6 ile Promise'ler yerleşik bir global tiptir. Onları kullan! +Callbacks aren't clean, and they cause excessive amounts of nesting. With ES2015/ES6, +Promises are a built-in global type. Use them! -**Kötü:** +**Bad:** ```javascript import { get } from "request"; @@ -1756,7 +1928,7 @@ get( ); ``` -**İyi:** +**Good:** ```javascript import { get } from "request-promise"; @@ -1774,13 +1946,17 @@ get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Async/Await kullanmak Promis kullanmaktan bile daha temiz +### Async/Await are even cleaner than Promises -Promise'ler callback'lere göte çok daha temiz alternatiflerdir, ama ES2017/ES8 async ve await getirdi ve bu daha temiz bir çözüm sunuyor. Tek yapmanız gereken fonksiyonun başına `async` eklemek ve sonrasında mantıksal kullanımızı `then` zinciri kulanmadan yazabilirsiniz. Bugün ES2017 / ES8 özelliklerinden yararlanabiliyorsanız bunu kullanın! +Promises are a very clean alternative to callbacks, but ES2017/ES8 brings async and await +which offer an even cleaner solution. All you need is a function that is prefixed +in an `async` keyword, and then you can write your logic imperatively without +a `then` chain of functions. Use this if you can take advantage of ES2017/ES8 features +today! -**Kötü:** +**Bad:** ```javascript import { get } from "request-promise"; @@ -1798,7 +1974,7 @@ get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") }); ``` -**İyi:** +**Good:** ```javascript import { get } from "request-promise"; @@ -1819,21 +1995,25 @@ async function getCleanCodeArticle() { getCleanCodeArticle() ``` -**[⬆ Başa dön](#İçindekiler)** - -## **Hata Yönetimi** - -Atılan hatalar iyi bir şey! Bunlar, programınızdaki bir şey yanlış gittiğinde çalışma zamanının başarıyla tanımlandığı anlamına gelir ve sizi geçerli yığında (stack) fonksiyonu çalıştırmayı, işlevi dururup size konsolda yığın izlemede haber vererek yapar. +**[⬆ back to top](#table-of-contents)** ---- HERE +## **Error Handling** -### Yakalanmış hataları görmemezlikten gelmeyin +Thrown errors are a good thing! They mean the runtime has successfully +identified when something in your program has gone wrong and it's letting +you know by stopping function execution on the current stack, killing the +process (in Node), and notifying you in the console with a stack trace. -Yakalanan bir hatayla hiçbir şey yapmamanız size söz konusu hatayı düzeltebilme veya tepki gösterme yeteneği vermez. Hatayı konsola (`console.log`) kaydetmek, konsola yazdırılan bir şey denizinde kaybolabileceği sıklıkta daha iyi değildir. +### Don't ignore caught errors -Herhangi bir kod parçasını `try/catch` içerisinde kullanıyorsanız, orada bir hata olabileceğini düşündüğünüz anlamına gelir ve bu nedenle gerçekleştiği zaman için bir planınız olması veya bir kod yolu oluşturmanız gerekir. +Doing nothing with a caught error doesn't give you the ability to ever fix +or react to said error. Logging the error to the console (`console.log`) +isn't much better as often times it can get lost in a sea of things printed +to the console. If you wrap any bit of code in a `try/catch` it means you +think an error may occur there and therefore you should have a plan, +or create a code path, for when it occurs. -**Kötü:** +**Bad:** ```javascript try { @@ -1843,27 +2023,28 @@ try { } ``` -**İyi:** +**Good:** ```javascript try { functionThatMightThrow(); } catch (error) { - // Bir secenek (console.log'dan daha dikkat çekici) + // One option (more noisy than console.log): console.error(error); - // Bir secenek daha + // Another option: notifyUserOfError(error); - // Bir secenek daha + // Another option: reportErrorToService(error); - // veya hepsini bir yapın + // OR do all three! } ``` -### Reddedilmiş promisleri görmemezlikten gelmeyin +### Don't ignore rejected promises -Aynı sebeplerden dolayı, `try/catch`'de oluşan hataları yok saymamalısınız +For the same reason you shouldn't ignore caught errors +from `try/catch`. -**Kötü:** +**Bad:** ```javascript getdata() @@ -1875,7 +2056,7 @@ getdata() }); ``` -**İyi:** +**Good:** ```javascript getdata() @@ -1883,29 +2064,36 @@ getdata() functionThatMightThrow(data); }) .catch(error => { - // Bir secenek (console.log'dan daha dikkat çekici) + // One option (more noisy than console.log): console.error(error); - // Bir secenek daha + // Another option: notifyUserOfError(error); - // Bir secenek daha + // Another option: reportErrorToService(error); - // veya hepsini bir yapın + // OR do all three! }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Biçimlendirme** +## **Formatting** -Biçimlendirme özneldir. Buradaki birçok kural gibi, uygulamanız gereken zor ve hızlı bir kural yoktur. Ana nokta biçimlendirme üzerinde tartışma DEĞİLDİR. Bunu otomatikleştirmek için [tonlarca araç](https://standardjs.com/rules.html) vardır. Birini kullan! Mühendislerin biçimlendirme konusunda tartışmaları zaman ve para kaybıdır. +Formatting is subjective. Like many rules herein, there is no hard and fast +rule that you must follow. The main point is DO NOT ARGUE over formatting. +There are [tons of tools](https://standardjs.com/rules.html) to automate this. +Use one! It's a waste of time and money for engineers to argue over formatting. -Otomatik biçimlendirme (girintileme, sekmeler ve boşluklar, çift veya tek tırnak işaretleri vb.) Kapsamına girmeyen şeyler için bazı rehberlik için buraya bakın. +For things that don't fall under the purview of automatic formatting +(indentation, tabs vs. spaces, double vs. single quotes, etc.) look here +for some guidance. -### Tutarlı büyük harf kullanımı +### Use consistent capitalization -JavaScript türsüzdür, bu nedenle büyük / küçük harf kullanımı değişkenleriniz, işlevleriniz vb. Hakkında çok şey anlatır. Bu kurallar özneldir, böylece ekibiniz istediklerini seçebilir. Mesele şu ki, ne seçerseniz seçin, tutarlı olun. +JavaScript is untyped, so capitalization tells you a lot about your variables, +functions, etc. These rules are subjective, so your team can choose whatever +they want. The point is, no matter what you all choose, just be consistent. -**Kötü:** +**Bad:** ```javascript const DAYS_IN_WEEK = 7; @@ -1921,7 +2109,7 @@ class animal {} class Alpaca {} ``` -**İyi:** +**Good:** ```javascript const DAYS_IN_WEEK = 7; @@ -1937,13 +2125,15 @@ class Animal {} class Alpaca {} ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksion çağıranları ve çağrılanları yakın olmalı +### Function callers and callees should be close -Eğer bir fonksiyon diğer fonksiyonu çağırıyorsa, dikey olarak bu fonksiyonları kaynak dosyasında yakın tutun. İdeal olan, fonksiyonu kullanan kullandığı fonksiyonun hemen üstünde olmasıdır. We tend to read code from top-to-bottom, like a newspaper.Bu nedenle, kodunuzu bu şekilde okuyun. +If a function calls another, keep those functions vertically close in the source +file. Ideally, keep the caller right above the callee. We tend to read code from +top-to-bottom, like a newspaper. Because of this, make your code read that way. -**Kötü:** +**Bad:** ```javascript class PerformanceReview { @@ -1983,7 +2173,7 @@ const review = new PerformanceReview(employee); review.perfReview(); ``` -**İyi:** +**Good:** ```javascript class PerformanceReview { @@ -2023,37 +2213,37 @@ const review = new PerformanceReview(employee); review.perfReview(); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Yorumlar** +## **Comments** -### Yalnızca iş mantığı karmaşıklığı olan şeyleri yorumlayın +### Only comment things that have business logic complexity. -Yorumlar aslında bir özür, şart değil. İyi kod _çoğunlukla_ kendini belgelemektedir. +Comments are an apology, not a requirement. Good code _mostly_ documents itself. -**Kötü:** +**Bad:** ```javascript function hashIt(data) { - // Karma + // The hash let hash = 0; - // String uzunluğu + // Length of string const length = data.length; - // Verilerdeki her karakteri gözden geçirin + // Loop through every character in data for (let i = 0; i < length; i++) { - // Karakter kodunu al + // Get character code. const char = data.charCodeAt(i); - // Karıştır + // Make the hash hash = (hash << 5) - hash + char; - // 32-bit tam sayıya dönüştür + // Convert to 32-bit integer hash &= hash; } } ``` -**İyi:** +**Good:** ```javascript function hashIt(data) { @@ -2064,19 +2254,19 @@ function hashIt(data) { const char = data.charCodeAt(i); hash = (hash << 5) - hash + char; - // 32-bit tam sayıya dönüştür + // Convert to 32-bit integer hash &= hash; } } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Kodlarınızı yorum olarak bırakmayın +### Don't leave commented out code in your codebase -Versiyon kontrol'un var olmasının bir sebebi var. Eski kodlarınızı tarihin tozlu sayfalarında bırakın. +Version control exists for a reason. Leave old code in your history. -**Kötü:** +**Bad:** ```javascript doStuff(); @@ -2085,19 +2275,20 @@ doStuff(); // doSoMuchStuff(); ``` -**İyi:** +**Good:** ```javascript doStuff(); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Günlük yorumları yapmayın +### Don't have journal comments -Hatırlayın, versiyon kontrol kullanın! Kullanılmayan koda, yoruma alınmış koda ve özellikle günlük kodlarına gerek yok. Geçmiş için `git log` kullanın. +Remember, use version control! There's no need for dead code, commented code, +and especially journal comments. Use `git log` to get history! -**Kötü:** +**Bad:** ```javascript /** @@ -2111,7 +2302,7 @@ function combine(a, b) { } ``` -**İyi:** +**Good:** ```javascript function combine(a, b) { @@ -2119,13 +2310,14 @@ function combine(a, b) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yer belirleyicilerden kaçının +### Avoid positional markers -Bunlar genellikle kirlilik yaratır. Fonksiyonların ve değişken adlarının yanı sıra uygun girinti ve biçimlendirme kodunuza görsel yapı kazandırsın. +They usually just add noise. Let the functions and variable names along with the +proper indentation and formatting give the visual structure to your code. -**Kötü:** +**Bad:** ```javascript //////////////////////////////////////////////////////////////////////////////// @@ -2144,7 +2336,7 @@ const actions = function() { }; ``` -**İyi:** +**Good:** ```javascript $scope.model = { @@ -2157,11 +2349,11 @@ const actions = function() { }; ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## Çeviriler +## Translation -Ayrıca diğer dillerde de: +This is also available in other languages: - ![am](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Armenia.png) **Armenian**: [hanumanum/clean-code-javascript/](https://github.com/hanumanum/clean-code-javascript) - ![bd](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bangladesh.png) **Bangla(বাংলা)**: [InsomniacSabbir/clean-code-javascript/](https://github.com/InsomniacSabbir/clean-code-javascript/) @@ -2182,7 +2374,6 @@ Ayrıca diğer dillerde de: - [maksugr/clean-code-javascript](https://github.com/maksugr/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [tureey/clean-code-javascript](https://github.com/tureey/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Uruguay.png) **Spanish**: [andersontr15/clean-code-javascript](https://github.com/andersontr15/clean-code-javascript-es) -- ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** From 60a33571e766b3aa05ac5c7cd0d871f035802d3e Mon Sep 17 00:00:00 2001 From: Burak Sonmez Date: Thu, 26 Mar 2020 08:43:25 +0300 Subject: [PATCH 11/24] Turkish added --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bbe7a083..af68982e 100644 --- a/README.md +++ b/README.md @@ -2374,6 +2374,7 @@ This is also available in other languages: - [maksugr/clean-code-javascript](https://github.com/maksugr/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [tureey/clean-code-javascript](https://github.com/tureey/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Uruguay.png) **Spanish**: [andersontr15/clean-code-javascript](https://github.com/andersontr15/clean-code-javascript-es) +- ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) **[⬆ back to top](#table-of-contents)** From 1470b0b5e4ca00feeb19cba28af4c8ee183ea305 Mon Sep 17 00:00:00 2001 From: Burak Sonmez Date: Thu, 26 Mar 2020 08:46:06 +0300 Subject: [PATCH 12/24] Turkish Added --- README.md | 900 +++++++++++++++++++++--------------------------------- 1 file changed, 354 insertions(+), 546 deletions(-) diff --git a/README.md b/README.md index af68982e..d7747ff9 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,55 @@ # clean-code-javascript -## Table of Contents +## İçindekiler -1. [Introduction](#introduction) -2. [Variables](#variables) -3. [Functions](#functions) -4. [Objects and Data Structures](#objects-and-data-structures) -5. [Classes](#classes) +1. [Giriş](#Giriş) +2. [Değişkenler](#Değişkenler) +3. [Fonksiyonlar](#Fonksiyonlar) +4. [Nesneler ve Veri Yapıları](#nesneler-ve-veri-yapıları) +5. [Sınıflar (Class)](#sınıflar) 6. [SOLID](#solid) -7. [Testing](#testing) -8. [Concurrency](#concurrency) -9. [Error Handling](#error-handling) -10. [Formatting](#formatting) -11. [Comments](#comments) -12. [Translation](#translation) +7. [Testler](#testler) +8. [Tutarlılık](#Tutarlılık) +9. [Hata Yönetimi](#Hata-Yönetimi) +10. [Biçimlendirme](#Biçimlendirme) +11. [Yorumlar](#yorumlar) +12. [Çeviriler](#çeviriler) -## Introduction +## Giriş -![Humorous image of software quality estimation as a count of how many expletives -you shout when reading code](https://www.osnews.com/images/comics/wtfm.jpg) +![Kod okurken kaç defa bağıracağınızın bir sayısı olarak yazılım kalite tahmininin görüntüsü](https://www.osnews.com/images/comics/wtfm.jpg) -Software engineering principles, from Robert C. Martin's book -[_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882), -adapted for JavaScript. This is not a style guide. It's a guide to producing -[readable, reusable, and refactorable](https://github.com/ryanmcdermott/3rs-of-software-architecture) software in JavaScript. +Robert C. Martin'nın kitabı olan ve yazılım mühendisliği ilkerini barındıran [_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)'un JavaScript için uyarlanmış hali. Bu bir tarz rehberi değil. JavaScript'te [okunabilir, yeniden kullanılabilir ve yeniden düzenlenebilir](https://github.com/ryanmcdermott/3rs-of-software-architecture) yazılımlar üretmeye yönelik bir kılavuzdur. -Not every principle herein has to be strictly followed, and even fewer will be -universally agreed upon. These are guidelines and nothing more, but they are -ones codified over many years of collective experience by the authors of -_Clean Code_. +Buradaki her ilkeye kesinlikle uyulmak zorunda değildir ve daha azı evrensel olarak kabul edilecektir. Bunlar önerilerden başka bir şey değildir, fakat bunlar _Clean Code_ yazarları tarafından uzun yıllar süren tecrübeler ile kodlandı. -Our craft of software engineering is just a bit over 50 years old, and we are -still learning a lot. When software architecture is as old as architecture -itself, maybe then we will have harder rules to follow. For now, let these -guidelines serve as a touchstone by which to assess the quality of the -JavaScript code that you and your team produce. +Yazılım mühendisliği zanaatımız 50 yaşın biraz üzerinde ve hala çok şey öğreniyoruz. Yazılım mimarisi, mimarinin kendisi kadar eski olduğunda, belki de takip edilmesi daha zor kurallarımız olacak. Şimdi, bu önerilerin sizin ve ekibinizin ürettiği JavaScript kodunun kalitesini değerlendirmek için bir mihenk taşı işlevi görmesine izin verin. -One more thing: knowing these won't immediately make you a better software -developer, and working with them for many years doesn't mean you won't make -mistakes. Every piece of code starts as a first draft, like wet clay getting -shaped into its final form. Finally, we chisel away the imperfections when -we review it with our peers. Don't beat yourself up for first drafts that need -improvement. Beat up the code instead! +Bir şey daha: bunların bilinmesi sizi hemen daha iyi bir yazılım geliştiricisi yapmaz ve uzun yıllar onlarla çalışmak hata yapmayacağınız anlamına gelmez. -## **Variables** +Her kod parçası ilk taslak olarak başlar, örneğin ıslak kil son halini alır. Son olarak, akranlarımızla gözden geçirdiğimizde kusurları kesiyoruz. İyileştirilmesi gereken ilk taslaklar için kendinize yüklenmeyin. Onun yerine kodunuza yüklenin. -### Use meaningful and pronounceable variable names +## **Değişkenler** -**Bad:** +### Anlamlı ve belirgin değişken adları kullanın + +**Kötü:** ```javascript const yyyymmdstr = moment().format("YYYY/MM/DD"); ``` -**Good:** +**İyi:** ```javascript const currentDate = moment().format("YYYY/MM/DD"); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use the same vocabulary for the same type of variable +### Aynı değişken türü için aynı kelimeleri kullanın -**Bad:** +**Kötü:** ```javascript getUserInfo(); @@ -71,45 +57,41 @@ getClientData(); getCustomerRecord(); ``` -**Good:** +**İyi:** ```javascript getUser(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use searchable names +### Aranabilir isimler kullanın -We will read more code than we will ever write. It's important that the code we -do write is readable and searchable. By _not_ naming variables that end up -being meaningful for understanding our program, we hurt our readers. -Make your names searchable. Tools like -[buddy.js](https://github.com/danielstjules/buddy.js) and -[ESLint](https://github.com/eslint/eslint/blob/660e0918933e6e7fede26bc675a0763a6b357c94/docs/rules/no-magic-numbers.md) -can help identify unnamed constants. +Yazacağımızdan daha fazla kod okuyacağız. Yazdığımız kodun okunabilir ve aranabilir olması önemlidir. Değişkenleri anlamlı ve anlaşılabilir _isimlendirmemekle_, okuyucuya zarar veriyoruz. +Adlarınızı aranabilir hale getirin. [buddy.js](https://github.com/danielstjules/buddy.js) ve +[ESLint](https://github.com/eslint/eslint/blob/660e0918933e6e7fede26bc675a0763a6b357c94/docs/rules/no-magic-numbers.md) gibi araçlar isimlendirilmemiş sabitlerinizi belirlemenize yardımcı olacaktır. -**Bad:** +**Kötü:** ```javascript -// What the heck is 86400000 for? +// 86400000 neydi ? setTimeout(blastOff, 86400000); ``` -**Good:** +**İyi:** ```javascript -// Declare them as capitalized named constants. +// Bunları büyük harfle adlandırılmış sabitler olarak bildirin. const MILLISECONDS_IN_A_DAY = 86_400_000; setTimeout(blastOff, MILLISECONDS_IN_A_DAY); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use explanatory variables +### Açıklayıcı değişkenler kullan -**Bad:** +**Kötü:** ```javascript const address = "One Infinite Loop, Cupertino 95014"; @@ -120,7 +102,7 @@ saveCityZipCode( ); ``` -**Good:** +**İyi:** ```javascript const address = "One Infinite Loop, Cupertino 95014"; @@ -129,13 +111,13 @@ const [_, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid Mental Mapping +### Kafadan planmaktan kaçının -Explicit is better than implicit. +Açık olmak, ima etmekten iyidir. -**Bad:** +**Kötü:** ```javascript const locations = ["Austin", "New York", "San Francisco"]; @@ -145,12 +127,12 @@ locations.forEach(l => { // ... // ... // ... - // Wait, what is `l` for again? + // Bir dakika, 'l' neydi? dispatch(l); }); ``` -**Good:** +**İyi:** ```javascript const locations = ["Austin", "New York", "San Francisco"]; @@ -164,14 +146,13 @@ locations.forEach(location => { }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Don't add unneeded context +### Gereksiz içerikler eklemeyin -If your class/object name tells you something, don't repeat that in your -variable name. +Sınıf / nesne adınız size bir şey söylüyorsa, bunu değişken adınızda tekrarlamayın. -**Bad:** +**Kötü:** ```javascript const Car = { @@ -185,7 +166,7 @@ function paintCar(car) { } ``` -**Good:** +**İyi:** ```javascript const Car = { @@ -199,16 +180,13 @@ function paintCar(car) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use default arguments instead of short circuiting or conditionals +### Kısa devre veya şartlar yerine önceden tanımlanmış argümanlar kullanın -Default arguments are often cleaner than short circuiting. Be aware that if you -use them, your function will only provide default values for `undefined` -arguments. Other "falsy" values such as `''`, `""`, `false`, `null`, `0`, and -`NaN`, will not be replaced by a default value. +Önceden tanımlanan argümanlar genellikle kısa devrelere göre daha temizdir. Bunları kullanırsanız şunun farkında olun, fonksiyonunuz sadece `tanımsız` _(undefined)_ değerler için önceden tanımlanmış argümana kullanacaktır. `''`, `""`, `false`, `null`, `0`, ve `NaN` gibi "yanlış denilebilecek" değerler önceden tanımlanmış bir değerle değiştirilmez. -**Bad:** +**Kötü:** ```javascript function createMicrobrewery(name) { @@ -217,7 +195,7 @@ function createMicrobrewery(name) { } ``` -**Good:** +**İyi:** ```javascript function createMicrobrewery(name = "Hipster Brew Co.") { @@ -225,41 +203,27 @@ function createMicrobrewery(name = "Hipster Brew Co.") { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Functions** +## **Fonksiyonlar** -### Function arguments (2 or fewer ideally) +### Fonksiyonlar argümanları (Tercihen 2 veya daha az) -Limiting the amount of function parameters is incredibly important because it -makes testing your function easier. Having more than three leads to a -combinatorial explosion where you have to test tons of different cases with -each separate argument. +Fonksiyon parametrelerinin sayısını sınırlamak inanılmaz derecede önemlidir, çünkü fonksiyonunuzu test etmeyi kolaylaştırır. Üçten fazlasına sahip olmak, her bir argümanla tonlarca farklı vakayı test etmeniz gereken bir kombinasyonel patlamaya yol açar. -One or two arguments is the ideal case, and three should be avoided if possible. -Anything more than that should be consolidated. Usually, if you have -more than two arguments then your function is trying to do too much. In cases -where it's not, most of the time a higher-level object will suffice as an -argument. +Bir veya iki argüman ideal durumdur ve mümkünse üç tanesinden kaçınılmalıdır. Bundan daha fazlası birleştirilmeldir. Genellikle, +ikiden fazla argüman sonra fonksiyonunuz çok işlem yapmaya çalışıyor. Olmadığı durumlarda, çoğu zaman daha üst düzey bir nesne argüman olarak yeterli olacaktır. -Since JavaScript allows you to make objects on the fly, without a lot of class -boilerplate, you can use an object if you are finding yourself needing a -lot of arguments. +JavaScript havada nesne yapmanıza olanak sağladığı için, bir çok sınıf yapısına gerek kalmadan, bir nesneyi birden fazla nesne kullanmadan kullanabilirsiniz. -To make it obvious what properties the function expects, you can use the ES2015/ES6 -destructuring syntax. This has a few advantages: +Fonksiyonun hangi özellikleri beklediğini netleştirmek için ES2015 / ES6 ayrıştırma sintaksını kullanabilirsiniz. Bunun birkaç avantajı vardır: -1. When someone looks at the function signature, it's immediately clear what - properties are being used. -2. It can be used to simulate named parameters. -3. Destructuring also clones the specified primitive values of the argument - object passed into the function. This can help prevent side effects. Note: - objects and arrays that are destructured from the argument object are NOT - cloned. -4. Linters can warn you about unused properties, which would be impossible - without destructuring. +1. Birisi fonksiyonun imzasına baktığında, hangi özelliklerin kullanıldığını hemen anlar.. +2. Adlandırılmış parametreleri simüle etmek için kullanılabilir. +3. Ayrıştırma işlemi ayrıca fonksiyona iletilen argüman nesnesinin belirtilen ilk değerlerini de klonlar. Bu, yan etkilerin önlenmesine yardımcı olabilir. Not: Argüman nesnelerinden ayrıştırılan nesneler ve diziler klonlanmaz! +4. Linters, sizi kullanılmayan değerler için uyarabilir bu da ayrıştırmadan imkansız olurdu. -**Bad:** +**Kötü:** ```javascript function createMenu(title, body, buttonText, cancellable) { @@ -270,7 +234,7 @@ createMenu("Foo", "Bar", "Baz", true); ``` -**Good:** +**İyi:** ```javascript function createMenu({ title, body, buttonText, cancellable }) { @@ -285,17 +249,13 @@ createMenu({ }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Functions should do one thing +### Fonksiyonlar bir şey yapmalı -This is by far the most important rule in software engineering. When functions -do more than one thing, they are harder to compose, test, and reason about. -When you can isolate a function to just one action, it can be refactored -easily and your code will read much cleaner. If you take nothing else away from -this guide other than this, you'll be ahead of many developers. +Bu, yazılım mühendisliğinde açık ara en önemli kuraldır. Fonksiyonlar birden fazla şey yaptığında, birleştirmesi, test etmesi ve anlamdırılması daha zordur. Bir fonksiyonu yalnızca bir eyleme ayırabildiğinizde, kolayca yeniden düzenlenebilir ve kodunuz çok daha temiz okunur. Bu yazıdan başka bir şey almazsanız dahi sadece bununla birçok geliştiricinin önünde olacaksınız. -**Bad:** +**Kötü:** ```javascript function emailClients(clients) { @@ -308,7 +268,7 @@ function emailClients(clients) { } ``` -**Good:** +**İyi:** ```javascript function emailActiveClients(clients) { @@ -321,11 +281,11 @@ function isActiveClient(client) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Function names should say what they do +### Fonksiyon isimleri ne yaptıklarını anlatmalı -**Bad:** +**Kötü:** ```javascript function addToDate(date, month) { @@ -334,11 +294,11 @@ function addToDate(date, month) { const date = new Date(); -// It's hard to tell from the function name what is added +// Fonksiyonun adından ne eklendiğini söylemek zor addToDate(date, 1); ``` -**Good:** +**İyi:** ```javascript function addMonthToDate(month, date) { @@ -349,15 +309,13 @@ const date = new Date(); addMonthToDate(1, date); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Functions should only be one level of abstraction +### Fonksiyonlar soyutlaştırmadan sadece bir seviye uzak olmalıdır -When you have more than one level of abstraction your function is usually -doing too much. Splitting up functions leads to reusability and easier -testing. +Birden fazla soyutlama seviyeniz olduğunda fonksiyonunuz genellikle çok fazla şey yapar. Fonksiyonların bölünmesi, yeniden kullanılabilirliği ve daha kolay test yapılmasını sağlayacak. -**Bad:** +**Kötü:** ```javascript function parseBetterJSAlternative(code) { @@ -384,7 +342,7 @@ function parseBetterJSAlternative(code) { } ``` -**Good:** +**İyi:** ```javascript function parseBetterJSAlternative(code) { @@ -421,32 +379,19 @@ function parse(tokens) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Remove duplicate code +### Tekrarlanan kodu sil -Do your absolute best to avoid duplicate code. Duplicate code is bad because it -means that there's more than one place to alter something if you need to change -some logic. +Tekrarlanan kodlardan kaçınmak için elinizden geleni yapın. Tekrarlanan kod kötü çünkü bazı mantığı değiştirmeniz gerekirse bir şeyi değiştirmek için birden fazla yer olduğu anlamına geliyor. -Imagine if you run a restaurant and you keep track of your inventory: all your -tomatoes, onions, garlic, spices, etc. If you have multiple lists that -you keep this on, then all have to be updated when you serve a dish with -tomatoes in them. If you only have one list, there's only one place to update! +Bir restoran işlettiğinizi ve stoklarınızı takip ettiğinizi düşünün: tüm domates, soğan, sarımsak, baharat, vb. onlara. Yalnızca bir listeniz varsa, güncellenecek tek bir yer vardır! -Oftentimes you have duplicate code because you have two or more slightly -different things, that share a lot in common, but their differences force you -to have two or more separate functions that do much of the same things. Removing -duplicate code means creating an abstraction that can handle this set of -different things with just one function/module/class. +Çoğunlukla yinelenen kodunuz vardır, çünkü çoğu şeyi ortak paylaşsalar dahi çok küçük bir kaç farklılık vardır, ancak farklılıkları sizi aynı şeylerin çoğunu yapan iki veya daha fazla ayrı fonksiyona sahip olmaya zorlar. Tekrarlanan kodun kaldırılması, bu farklı şeyleri tek bir fonksiyon / modül / sınıfla işleyebilecek bir soyutlama oluşturmak anlamına gelir. -Getting the abstraction right is critical, that's why you should follow the -SOLID principles laid out in the _Classes_ section. Bad abstractions can be -worse than duplicate code, so be careful! Having said this, if you can make -a good abstraction, do it! Don't repeat yourself, otherwise you'll find yourself -updating multiple places anytime you want to change one thing. +Soyutlamayı doğru yapmak kritik öneme sahiptir, bu yüzden _Sınıflar_ bölümünde belirtilen SOLID ilkelerini izlemelisiniz. Kötü soyutlamalar yinelenen koddan daha kötü olabilir, bu yüzden dikkatli olun! Bunu söyledikten sonra, eğer iyi bir soyutlama yapabilirseniz, yapın! Kendinizi tekrarlamayın, aksi takdirde bir şeyi değiştirmek istediğinizde kendinizi birden fazla yeri güncellerken bulacaksınız. -**Bad:** +**Kötü:** ```javascript function showDeveloperList(developers) { @@ -480,7 +425,7 @@ function showManagerList(managers) { } ``` -**Good:** +**İyi:** ```javascript function showEmployeeList(employees) { @@ -507,11 +452,11 @@ function showEmployeeList(employees) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Set default objects with Object.assign +### Object.assign ile varsayılan nesneleri ayarlama -**Bad:** +**Kötü:** ```javascript const menuConfig = { @@ -532,12 +477,12 @@ function createMenu(config) { createMenu(menuConfig); ``` -**Good:** +**İyi:** ```javascript const menuConfig = { title: "Order", - // User did not include 'body' key + // Kullanıcı 'body' eklemedi buttonText: "Send", cancellable: true }; @@ -553,20 +498,20 @@ function createMenu(config) { config ); - // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} + // config çıktısı şimdi : {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } createMenu(menuConfig); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Don't use flags as function parameters +### Fonksiyon parametrelerinde işaretleme kullanma -Flags tell your user that this function does more than one thing. Functions should do one thing. Split out your functions if they are following different code paths based on a boolean. +İşaretlemeler fonksiyonunuzun birden fazla şey yaptığını gösterir. Fonkisyonlar sadece tek şey yapmalılar. Eğer aşağıdakine benzer değişiklere ve mantıksal operatorlere sahip fonksiyonunuz varsa fonksiyonlarınızı ayırın. -**Bad:** +**Kötü:** ```javascript function createFile(name, temp) { @@ -578,7 +523,7 @@ function createFile(name, temp) { } ``` -**Good:** +**İyi:** ```javascript function createFile(name) { @@ -590,30 +535,21 @@ function createTempFile(name) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid Side Effects (part 1) +### Yan Etkilerden Kaçının (Bölüm 1) -A function produces a side effect if it does anything other than take a value in -and return another value or values. A side effect could be writing to a file, -modifying some global variable, or accidentally wiring all your money to a -stranger. +Bir fonksiyon, bir değeri alıp başka bir değer veya değer döndürmekten başka bir şey yaparsa yan etki üretir. Bir yan etki, bir dosyaya yazma, bazı global değişkeni değiştirme veya yanlışlıkla tüm paranızı bir yabancıya gönderme olabilir. -Now, you do need to have side effects in a program on occasion. Like the previous -example, you might need to write to a file. What you want to do is to -centralize where you are doing this. Don't have several functions and classes -that write to a particular file. Have one service that does it. One and only one. +Şimdi, zaman zaman bir programda yan etkilere sahip olmanız gerekir. Önceki örnekte olduğu gibi, bir dosyaya yazmanız gerekebilir. Yapmak istediğiniz, bunu yapacağınız yeri merkezileştirmektir. Birden fazla yazma işlemi yapan fonksiyonlar veya sınıflar yapmayın. Bunu yapan bir servisiniz olsun. Bir ve sadece bir. -The main point is to avoid common pitfalls like sharing state between objects -without any structure, using mutable data types that can be written to by anything, -and not centralizing where your side effects occur. If you can do this, you will -be happier than the vast majority of other programmers. +Buradaki ana nokta, herhangi bir yapıya sahip olmayan nesneler arasında durumu(state) paylaşmak, herhangi bir şeyle yazılabilen değiştirilebilir(mutable) veri türlerini kullanmak ve yan etkilerinizin nerede ortaya çıktığını merkezileştirmemek gibi yaygın tuzaklardan kaçınmaktır. Bunu yapabilirseniz, diğer programcıların büyük çoğunluğundan daha mutlu olacaksınız. -**Bad:** +**Kötü:** ```javascript -// Global variable referenced by following function. -// If we had another function that used this name, now it'd be an array and it could break it. +// Aşağıdaki fonksiyon Global değişkeni refere alıyor +// Bu adı kullanan başka bir fonksiyonumuz olsaydı, şimdi bir dizi olurdu ve onu bozacaktı. let name = "Ryan McDermott"; function splitIntoFirstAndLastName() { @@ -625,7 +561,7 @@ splitIntoFirstAndLastName(); console.log(name); // ['Ryan', 'McDermott']; ``` -**Good:** +**İyi:** ```javascript function splitIntoFirstAndLastName(name) { @@ -639,44 +575,27 @@ console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott']; ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid Side Effects (part 2) +### Yan Etkilerden Kaçının (Bölüm 2) -In JavaScript, primitives are passed by value and objects/arrays are passed by -reference. In the case of objects and arrays, if your function makes a change -in a shopping cart array, for example, by adding an item to purchase, -then any other function that uses that `cart` array will be affected by this -addition. That may be great, however it can be bad too. Let's imagine a bad -situation: +JavaScript'te, temel öğeler değerlerle aktarılır (passed by value) ve objeler/diziler referans ile aktarılır (passed by reference). -The user clicks the "Purchase" button which calls a `purchase` function that -spawns a network request and sends the `cart` array to the server. Because -of a bad network connection, the `purchase` function has to keep retrying the -request. Now, what if in the meantime the user accidentally clicks "Add to Cart" -button on an item they don't actually want before the network request begins? -If that happens and the network request begins, then that purchase function -will send the accidentally added item because it has a reference to a shopping -cart array that the `addItemToCart` function modified by adding an unwanted -item. +Bu durumda, nesnelerde ve dizilerde fonksiyonunuz bir değişiklik yaparsa +örneğin, bir alışveriş sepeti dizisinde, satın almak için bir öğe ekleyerek, +bu `cart` dizisini kullanan diğer fonksiyonlar bu eklemeden etkilenecektir. +Bu harika olabilir, ancak kötü de olabilir. Kötü bir hayal edelim +durum: -A great solution would be for the `addItemToCart` to always clone the `cart`, -edit it, and return the clone. This ensures that no other functions that are -holding onto a reference of the shopping cart will be affected by any changes. +Kullanıcı, 'Satın Al' butonuna basar ve bu `satınal` fonksiyonu sunucuya bir istek atarak `sepet` dizisini sunucuya gönderir. Kötü bir ağ bağlantısı nedeniyle, `satınal` işlevi isteği yeniden denemeye devam etmelidir. Şimdi, bu arada kullanıcı yanlışlıkla ağ isteği başlamadan istemedikleri bir öğenin üzerine "Sepete Ekle" düğmesini tıklarsa ne olur? Bu olursa ve ağ isteği başlarsa, yanlışlıkla satın alınan öğeyi gönderir çünkü alışveriş sepeti dizisine, `ürünüSepeteEkle` işlevinin istenmeyen bir öğe ekleyerek değiştirdiği bir referansı vardır. `ürünüSepeteEkle` ın her zaman `sepeti` klonlaması, düzenlemesi ve klonu döndürmesi için harika bir çözüm olacaktır. Bu, alışveriş sepetinin referansını tutan başka hiçbir işlevin herhangi bir değişiklikten etkilenmemesini sağlar. -Two caveats to mention to this approach: +Bu yaklaşıma değinecek iki uyarı: -1. There might be cases where you actually want to modify the input object, - but when you adopt this programming practice you will find that those cases - are pretty rare. Most things can be refactored to have no side effects! +1. Girilen nesnesini gerçekten değiştirmek istediğiniz durumlar olabilir, ancak bunu uyguladığınızda, bu vakaların oldukça nadir olduğunu göreceksiniz. Çoğu şeyin yan etkisi olmayacak şekilde yeniden düzenlenebilir! -2. Cloning big objects can be very expensive in terms of performance. Luckily, - this isn't a big issue in practice because there are - [great libraries](https://facebook.github.io/immutable-js/) that allow - this kind of programming approach to be fast and not as memory intensive as - it would be for you to manually clone objects and arrays. +2. Büyük nesneleri klonlamak performans açısından çok pahalı olabilir. Neyse ki, bu pratikte büyük bir sorun değildir, çünkü bu tür programlama yaklaşımlarını manuel yapmaktansa daha hızlı olmasını ve büyük nesneleri ve dizileri klonlanlarken daha az bellek harcayan [harika kütüphaneler](https://facebook.github.io/immutable-js/) vardır. -**Bad:** +**Kötü:** ```javascript const addItemToCart = (cart, item) => { @@ -684,7 +603,7 @@ const addItemToCart = (cart, item) => { }; ``` -**Good:** +**İyi:** ```javascript const addItemToCart = (cart, item) => { @@ -692,21 +611,17 @@ const addItemToCart = (cart, item) => { }; ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** + +### Global fonksiyonlar yazma -### Don't write to global functions +Globalleri kirletmek JavaScript'te kötü bir uygulamadır, çünkü başka bir kütüphaneyle çakıştırabilirsiniz ve API'lerinizi kullananlar kişiler canlıya çıkana kadar bu aksi durumların farkında olmayabilir. -Polluting globals is a bad practice in JavaScript because you could clash with another -library and the user of your API would be none-the-wiser until they get an -exception in production. Let's think about an example: what if you wanted to -extend JavaScript's native Array method to have a `diff` method that could -show the difference between two arrays? You could write your new function -to the `Array.prototype`, but it could clash with another library that tried -to do the same thing. What if that other library was just using `diff` to find -the difference between the first and last elements of an array? This is why it -would be much better to just use ES2015/ES6 classes and simply extend the `Array` global. +Bir örnek düşünelim: JavaScript'in yerel kütüphanesindeki dizi `diff` methodunu genişletmek ve iki dizinin farklılıklarını göstermek istediğinizi var sayalım. JavaScript'in yerel Array yöntemini iki dizi arasındaki farkı gösterebilecek bir "diff" yöntemine genişletmek mi istiyorsunuz? -**Bad:** +Yeni fonksiyonunuzu `Array.prototype`'e yazabilirsiniz, ancak aynı şeyi yapmaya çalışan başka bir kütüphane ile çakışabilir. Ya diğer kütüphane bir dizinin ilk ve son elemanları arasındaki farkı bulmak için sadece `diff` kullanıyorsa? Bu yüzden sadece ES2015 / ES6 sınıflarını kullanmak ve `Array` globalini genişletmek çok daha iyi olurdu. + +**Kötü:** ```javascript Array.prototype.diff = function diff(comparisonArray) { @@ -715,7 +630,7 @@ Array.prototype.diff = function diff(comparisonArray) { }; ``` -**Good:** +**İyi:** ```javascript class SuperArray extends Array { @@ -726,15 +641,13 @@ class SuperArray extends Array { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Favor functional programming over imperative programming +### Zorunlu programlama yerine fonksiyonel programlamayı tercih edin -JavaScript isn't a functional language in the way that Haskell is, but it has -a functional flavor to it. Functional languages can be cleaner and easier to test. -Favor this style of programming when you can. +JavaScript, Haskell'in olduğu gibi işlevsel bir dil değildir, ancak işlevsel bir tadı vardır. İşlevsel diller daha temiz ve test edilmesi daha kolay olabilir. Yapabildiğinizde bu tarz bir programlama yapın. -**Bad:** +**Kötü:** ```javascript const programmerOutput = [ @@ -763,7 +676,7 @@ for (let i = 0; i < programmerOutput.length; i++) { } ``` -**Good:** +**İyi:** ```javascript const programmerOutput = [ @@ -791,11 +704,11 @@ const totalOutput = programmerOutput.reduce( ); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Encapsulate conditionals +### Koşulları kapsamak -**Bad:** +**Kötü:** ```javascript if (fsm.state === "fetching" && isEmpty(listNode)) { @@ -803,7 +716,7 @@ if (fsm.state === "fetching" && isEmpty(listNode)) { } ``` -**Good:** +**İyi:** ```javascript function shouldShowSpinner(fsm, listNode) { @@ -815,11 +728,11 @@ if (shouldShowSpinner(fsmInstance, listNodeInstance)) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** ### Avoid negative conditionals -**Bad:** +**Kötü:** ```javascript function isDOMNodeNotPresent(node) { @@ -831,7 +744,7 @@ if (!isDOMNodeNotPresent(node)) { } ``` -**Good:** +**İyi:** ```javascript function isDOMNodePresent(node) { @@ -843,20 +756,14 @@ if (isDOMNodePresent(node)) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid conditionals +### Koşullardan kaçının -This seems like an impossible task. Upon first hearing this, most people say, -"how am I supposed to do anything without an `if` statement?" The answer is that -you can use polymorphism to achieve the same task in many cases. The second -question is usually, "well that's great but why would I want to do that?" The -answer is a previous clean code concept we learned: a function should only do -one thing. When you have classes and functions that have `if` statements, you -are telling your user that your function does more than one thing. Remember, -just do one thing. +Bu imkansız bir görev gibi görünüyor. Bunu ilk kez duyduktan sonra, çoğu kişi "`if` ifadesi olmadan nasıl bir şey yapmam gerekiyor?" Cevap şu ki +birçok durumda aynı görevi yerine getirmek için polimorfizm kullanabilirsiniz. İkinci soru genellikle, "peki bu harika ama neden bunu yapmak isteyeyim ki?" Cevap, daha önce öğrendiğimiz temiz bir kod kavramıydı: bir fonksiyon sadece bir şey yapmalı. `If` ifadeleri olan sınıflarınız ve fonksiyonlarınız olduğunda, kullanıcılara işlevinizin birden fazla şey yaptığını söylüyor. Unutmayın, sadece bir şey yapın. -**Bad:** +**Kötü:** ```javascript class Airplane { @@ -874,7 +781,7 @@ class Airplane { } ``` -**Good:** +**İyi:** ```javascript class Airplane { @@ -903,16 +810,13 @@ class Cessna extends Airplane { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid type-checking (part 1) +### Yazım denetiminden kaçının (Bölüm 1) -JavaScript is untyped, which means your functions can take any type of argument. -Sometimes you are bitten by this freedom and it becomes tempting to do -type-checking in your functions. There are many ways to avoid having to do this. -The first thing to consider is consistent APIs. +JavaScript türsüzdür, yani işlevleriniz her türlü argümanı alabilir. Bazen bu özgürlük bizi oltaya getirebilir ve fonksiyonlarınızda tip kontrolü yapmak cazip hale gelir. Bunu yapmaktan kaçınmanın birçok yolu vardır. Dikkate alınması gereken ilk şey tutarlı API'lardır. -**Bad:** +**Kötü:** ```javascript function travelToTexas(vehicle) { @@ -924,7 +828,7 @@ function travelToTexas(vehicle) { } ``` -**Good:** +**İyi:** ```javascript function travelToTexas(vehicle) { @@ -932,21 +836,14 @@ function travelToTexas(vehicle) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid type-checking (part 2) +### Yazım denetiminden kaçının (Bölüm 2) -If you are working with basic primitive values like strings and integers, -and you can't use polymorphism but you still feel the need to type-check, -you should consider using TypeScript. It is an excellent alternative to normal -JavaScript, as it provides you with static typing on top of standard JavaScript -syntax. The problem with manually type-checking normal JavaScript is that -doing it well requires so much extra verbiage that the faux "type-safety" you get -doesn't make up for the lost readability. Keep your JavaScript clean, write -good tests, and have good code reviews. Otherwise, do all of that but with -TypeScript (which, like I said, is a great alternative!). +Dizeler ve tamsayılar gibi temel ilkel değerlerle çalışıyorsanız, +ve polimorfizm kullanamazsınız, ancak yine de yazım denetimi yapma gereğini hissediyorsanız, TypeScript kullanmayı düşünmelisiniz. Standart JavaScript sentaks üstünde statik yazım sağladığı için normal JavaScript'e mükemmel bir alternatiftir. Manuel olarak normal JavaScript'i kontrol etmeyle ilgili sorun, iyi yapmak o kadar fazla ayrıntılı gerektirir ki, elde ettiğiniz sahte "tip güvenliği" kaybettiğiniz okunabilirliği telafi etmez. JavaScript'inizi temiz tutun, iyi testler yazın ve iyi kod incelemelerine sahip olun. Aksi takdirde, hepsini TypeScript ile yapın (dediğim gibi harika bir alternatif!). -**Bad:** +**Kötü:** ```javascript function combine(val1, val2) { @@ -961,7 +858,7 @@ function combine(val1, val2) { } ``` -**Good:** +**İyi:** ```javascript function combine(val1, val2) { @@ -969,27 +866,25 @@ function combine(val1, val2) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** + +### Aşırı optimizasyon yapma -### Don't over-optimize +Modern tarayıcılar çalışma zamanında çok sayıda optimizasyon yapar. Çoğu zaman, eğer optimize ediyorsanız, sadece zamanınızı boşa harcıyorsunuz demektir. -Modern browsers do a lot of optimization under-the-hood at runtime. A lot of -times, if you are optimizing then you are just wasting your time. [There are good -resources](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) -for seeing where optimization is lacking. Target those in the meantime, until -they are fixed if they can be. +Optimizasyonun nerede olmadığını görmek için [iyi kaynaklar](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) vardır. Bunları optimize edene kadar işaretleyebilirsiniz. -**Bad:** +**Kötü:** ```javascript -// On old browsers, each iteration with uncached `list.length` would be costly -// because of `list.length` recomputation. In modern browsers, this is optimized. +// Eski tarayıcılarda, önbelleğe alınmamış "list.length" içeren her yineleme maliyetli olacaktır +// list.length yeniden hesaplanması nedeniyle. Modern tarayıcılarda bu optimize edilmiştir. for (let i = 0, len = list.length; i < len; i++) { // ... } ``` -**Good:** +**İyi:** ```javascript for (let i = 0; i < list.length; i++) { @@ -997,15 +892,13 @@ for (let i = 0; i < list.length; i++) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Remove dead code +### Kullanılmayan kodları silin -Dead code is just as bad as duplicate code. There's no reason to keep it in -your codebase. If it's not being called, get rid of it! It will still be safe -in your version history if you still need it. +Ölü kod, yinelenen kod kadar kötü. Kod tabanınızda tutmak için bir neden yoktur. Eğer çağrılmazsa, ondan kurtulun! Hala ihtiyacınız varsa sürüm geçmişinizde güvende olacaktır. -**Bad:** +**Kötü:** ```javascript function oldRequestModule(url) { @@ -1020,7 +913,7 @@ const req = newRequestModule; inventoryTracker("apples", req, "www.inventory-awesome.io"); ``` -**Good:** +**İyi:** ```javascript function newRequestModule(url) { @@ -1031,25 +924,21 @@ const req = newRequestModule; inventoryTracker("apples", req, "www.inventory-awesome.io"); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Objects and Data Structures** +## **Nesneler ve Veri Yapıları** -### Use getters and setters +### Alıcıları ve ayarlayıcıları kullanma (Getters & Setters) -Using getters and setters to access data on objects could be better than simply -looking for a property on an object. "Why?" you might ask. Well, here's an -unorganized list of reasons why: +Nesnelerdeki verilere erişmek için alıcıları ve ayarlayıcıları kullanmak, bir nesnedeki bir özelliği aramaktan daha iyi olabilir. "Neden?" sorabilirsiniz. Pekala, işte organize edilmeden nedenlerin bir listesi: -- When you want to do more beyond getting an object property, you don't have - to look up and change every accessor in your codebase. -- Makes adding validation simple when doing a `set`. -- Encapsulates the internal representation. -- Easy to add logging and error handling when getting and setting. -- You can lazy load your object's properties, let's say getting it from a - server. +- Bir nesne özelliği almanın ötesinde daha fazlasını yapmak istediğinizde, kod tabanınızdaki her erişimciye bakmanız ve değiştirmeniz gerekmez. +- `set`yaparken doğrulama basitçe yapılabilir. +- Dahili gösterimi içine alır. +- Alma ve ayarlama sırasında kayıtlamayı(logging) ve hata yönetimi(error handling) eklemek kolaydır. +- Diyelimki sunucudan alıyorsunuz, nesnenizin özelliklerini tembel(lazy load) olarak yükleyebilirsiniz. -**Bad:** +**Kötü:** ```javascript function makeBankAccount() { @@ -1065,19 +954,19 @@ const account = makeBankAccount(); account.balance = 100; ``` -**Good:** +**İyi:** ```javascript function makeBankAccount() { - // this one is private + // Bu fonksiyon özelinde (private) let balance = 0; - // a "getter", made public via the returned object below + // "alıcı"yı, genel(public) objeyi döndürerek yap function getBalance() { return balance; } - - // a "setter", made public via the returned object below + + // "ayarlayıcı"yı, genel(public) objeyi döndürerek yap function setBalance(amount) { // ... validate before updating the balance balance = amount; @@ -1094,13 +983,13 @@ const account = makeBankAccount(); account.setBalance(100); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Make objects have private members +### Nesnelerin özel üyeleri olmasını sağlama This can be accomplished through closures (for ES5 and below). -**Bad:** +**Kötü:** ```javascript const Employee = function(name) { @@ -1117,7 +1006,7 @@ delete employee.name; console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined ``` -**Good:** +**İyi:** ```javascript function makeEmployee(name) { @@ -1134,18 +1023,15 @@ delete employee.name; console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Classes** +## **Sınıflar** -### Prefer ES2015/ES6 classes over ES5 plain functions +### ES5 düz fonksiyonlar yerine ES2015 / ES6 sınıflarını tercih et -It's very difficult to get readable class inheritance, construction, and method -definitions for classical ES5 classes. If you need inheritance (and be aware -that you might not), then prefer ES2015/ES6 classes. However, prefer small functions over -classes until you find yourself needing larger and more complex objects. +Klasik ES5 sınıfları için okunabilir sınıf mirası, yapısı ve yöntem tanımları almak çok zordur. Miras almaya(inheritance) ihtiyacınız varsa (ve gerekmeyebileceğini unutmayın), ES2015 / ES6 sınıflarını tercih edin. Bununla birlikte, kendinizi daha büyük ve daha karmaşık nesnelere ihtiyaç duyana kadar küçük işlevlere tercih edin. -**Bad:** +**Kötü:** ```javascript const Animal = function(age) { @@ -1185,7 +1071,7 @@ Human.prototype.constructor = Human; Human.prototype.speak = function speak() {}; ``` -**Good:** +**İyi:** ```javascript class Animal { @@ -1221,17 +1107,13 @@ class Human extends Mammal { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Use method chaining +### Yöntem zincirini kullan -This pattern is very useful in JavaScript and you see it in many libraries such -as jQuery and Lodash. It allows your code to be expressive, and less verbose. -For that reason, I say, use method chaining and take a look at how clean your code -will be. In your class functions, simply return `this` at the end of every function, -and you can chain further class methods onto it. +Bu desen JavaScript'te çok kullanışlıdır ve jQuery ve Lodash gibi birçok kütüphanede görürsünüz. Kodunuzun etkileyici ve daha az detaylı olmasını sağlar. Bu nedenle, diyorum ki, yöntem zincirleme kullanın ve kodunuzun ne kadar temiz olacağını göreceksiniz. Sınıf fonksiyonlarınızda, her fonksiyonun sonunda `this`'i döndürmeniz yeterlidir ve daha fazla sınıf yöntemini buna zincirleyebilirsiniz. -**Bad:** +**Kötü:** ```javascript class Car { @@ -1263,7 +1145,7 @@ car.setColor("pink"); car.save(); ``` -**Good:** +**İyi:** ```javascript class Car { @@ -1275,25 +1157,25 @@ class Car { setMake(make) { this.make = make; - // NOTE: Returning this for chaining + // NOT: Zincirleme için `this` döndür return this; } setModel(model) { this.model = model; - // NOTE: Returning this for chaining + // NOT: Zincirleme için `this` döndür return this; } setColor(color) { this.color = color; - // NOTE: Returning this for chaining + // NOT: Zincirleme için `this` döndür return this; } save() { console.log(this.make, this.model, this.color); - // NOTE: Returning this for chaining + // NOT: Zincirleme için `this` döndür return this; } } @@ -1301,28 +1183,19 @@ class Car { const car = new Car("Ford", "F-150", "red").setColor("pink").save(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Prefer composition over inheritance +### Miras yerine kompozisyon tercih et -As stated famously in [_Design Patterns_](https://en.wikipedia.org/wiki/Design_Patterns) by the Gang of Four, -you should prefer composition over inheritance where you can. There are lots of -good reasons to use inheritance and lots of good reasons to use composition. -The main point for this maxim is that if your mind instinctively goes for -inheritance, try to think if composition could model your problem better. In some -cases it can. +Dörtlü çete tarafından başlatılan ünlü [_Tasarım Desenleri_](https://en.wikipedia.org/wiki/Design_Patterns) gibi, siz de kompozisyonu, miras bırakmaya yerine göre tercih etmelisiniz. Miras kullanmak için birçok iyi neden ve kompozisyon kullanmak için birçok iyi neden vardır. Bu maksimum nokta için ana nokta, zihniniz içgüdüsel olarak miras kullanma için giderse, kompozisyon sorununuzu daha iyi modelleyip değiştiremeyeceğini düşünmeye çalışın. Bazı durumlarda olabilir. -You might be wondering then, "when should I use inheritance?" It -depends on your problem at hand, but this is a decent list of when inheritance -makes more sense than composition: +O zaman "ne zaman miras kullanmalıyım?" diye merak ediyor olabilirsiniz. O eldeki probleminize bağlıdır, ancak bu mirasın kompozisyondan daha mantıklı olduğu iyi bir listedir: -1. Your inheritance represents an "is-a" relationship and not a "has-a" - relationship (Human->Animal vs. User->UserDetails). -2. You can reuse code from the base classes (Humans can move like all animals). -3. You want to make global changes to derived classes by changing a base class. - (Change the caloric expenditure of all animals when they move). +1. Mirasınız "has-a" değil, "is-a" ilişkisini temsil eder ilişki (İnsan-> Hayvan ve Kullanıcı-> KullanıcıAyrıntıları). +2. Temel sınıflardan kodu yeniden kullanabilirsiniz (İnsanlar tüm hayvanlar gibi hareket edebilir). +3. Temel sınıfı değiştirerek türetilmiş sınıflarda genel değişiklikler yapmak istiyorsunuz. (Hareket ettiklerinde tüm hayvanların kalori harcamalarını değiştirin). -**Bad:** +**Kötü:** ```javascript class Employee { @@ -1334,7 +1207,7 @@ class Employee { // ... } -// Bad because Employees "have" tax data. EmployeeTaxData is not a type of Employee +// Kötü çünkü Çalışanların(Employees) vergi bilgisi 'var'. ÇalışanVergiBilgisi(EmployeeTaxData) bir çeşit Çalışan(Employee) değil. class EmployeeTaxData extends Employee { constructor(ssn, salary) { super(); @@ -1346,7 +1219,7 @@ class EmployeeTaxData extends Employee { } ``` -**Good:** +**İyi:** ```javascript class EmployeeTaxData { @@ -1371,22 +1244,15 @@ class Employee { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** ## **SOLID** -### Single Responsibility Principle (SRP) +### Tek Sorumluluk İlkesi (SRP) -As stated in Clean Code, "There should never be more than one reason for a class -to change". It's tempting to jam-pack a class with a lot of functionality, like -when you can only take one suitcase on your flight. The issue with this is -that your class won't be conceptually cohesive and it will give it many reasons -to change. Minimizing the amount of times you need to change a class is important. -It's important because if too much functionality is in one class and you modify -a piece of it, it can be difficult to understand how that will affect other -dependent modules in your codebase. +Temiz Kod'da belirtildiği gibi, "Bir sınıfın değişmesi için asla birden fazla sebep olmamalıdır". Bir sınıfı tıklım tıklım bir çok işlevsellikle doldurmak çekici gelebilir, tıpkı uçuşlarda yanına alabileceğiniz bir valiz gibi. Bununla ilgili sorun, sınıfınızın kavramsal olarak uyumlu olmayacağı ve değişmesi için birçok neden vereceği yönündedir. Bir sınıfı değiştirmek için ihtiyaç duyduğunuz sayıyı en aza indirmek önemlidir. Bir sınıfta çok fazla işlevsellik varsa ve bir parçasını değiştirirseniz, bunun kod tabanınızdaki diğer bağımlı modülleri nasıl etkileyeceğini anlamak zor olabilir. -**Bad:** +**Kötü:** ```javascript class UserSettings { @@ -1406,7 +1272,7 @@ class UserSettings { } ``` -**Good:** +**İyi:** ```javascript class UserAuth { @@ -1433,16 +1299,13 @@ class UserSettings { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Open/Closed Principle (OCP) +### Açık / Kapalı Prensibi (OCP) -As stated by Bertrand Meyer, "software entities (classes, modules, functions, -etc.) should be open for extension, but closed for modification." What does that -mean though? This principle basically states that you should allow users to -add new functionalities without changing existing code. +Bertrand Meyer tarafından belirtildiği gibi, "yazılım varlıkları (sınıflar, modüller, işlevler, vb.) Genişletme için açık, ancak değişiklik için kapalı olmalıdır." Bu ne anlama geliyor? Bu ilke, temel olarak kullanıcıların mevcut kodu değiştirmeden yeni işlevler eklemelerine izin vermeniz gerektiğini belirtir. -**Bad:** +**Kötü:** ```javascript class AjaxAdapter extends Adapter { @@ -1486,7 +1349,7 @@ function makeHttpCall(url) { } ``` -**Good:** +**İyi:** ```javascript class AjaxAdapter extends Adapter { @@ -1524,24 +1387,15 @@ class HttpRequester { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Liskov Substitution Principle (LSP) +### Liskov’un Yerine Geçme Prensibi (LSP) -This is a scary term for a very simple concept. It's formally defined as "If S -is a subtype of T, then objects of type T may be replaced with objects of type S -(i.e., objects of type S may substitute objects of type T) without altering any -of the desirable properties of that program (correctness, task performed, -etc.)." That's an even scarier definition. +Bu çok basit bir kavram için korkutucu bir terimdir.Resmi olarak "S, T'nin bir alt tipiyse, o zaman T tipi nesnelerin yerine S tipi nesneler (yani, S tipi nesneler T programındaki nesnelerin yerine geçebilir), bu programın istenen özelliklerini değiştirmeden değiştirilebilir (doğruluk, yapılan görev vb.) " Bu daha da korkunç bir tanım. -The best explanation for this is if you have a parent class and a child class, -then the base class and child class can be used interchangeably without getting -incorrect results. This might still be confusing, so let's take a look at the -classic Square-Rectangle example. Mathematically, a square is a rectangle, but -if you model it using the "is-a" relationship via inheritance, you quickly -get into trouble. +Bunun için en iyi açıklama, bir üst sınıfınız ve bir alt sınıfınız varsa, temel sınıf ve alt sınıf yanlış sonuçlar elde etmeden birbirinin yerine kullanılabilir.Bu hala kafa karıştırıcı olabilir, bu yüzden klasik Kare Dikdörtgen örneğine bakalım. Matematiksel olarak, bir kare bir dikdörtgendir, ancak miras yoluyla "is-a" ilişkisini kullanarak model verirseniz, hızlı bir şekilde sorun yaşarsınız. -**Bad:** +**Kötü:** ```javascript class Rectangle { @@ -1587,7 +1441,7 @@ function renderLargeRectangles(rectangles) { rectangles.forEach(rectangle => { rectangle.setWidth(4); rectangle.setHeight(5); - const area = rectangle.getArea(); // BAD: Returns 25 for Square. Should be 20. + const area = rectangle.getArea(); // KÖTÜ: Kare için 25 değerini döndürür. 20 olmalı. rectangle.render(area); }); } @@ -1596,7 +1450,7 @@ const rectangles = [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles(rectangles); ``` -**Good:** +**İyi:** ```javascript class Shape { @@ -1643,25 +1497,17 @@ const shapes = [new Rectangle(4, 5), new Rectangle(4, 5), new Square(5)]; renderLargeShapes(shapes); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Interface Segregation Principle (ISP) +### Arayüzlerin Ayrımı Prensibi (ISP) -JavaScript doesn't have interfaces so this principle doesn't apply as strictly -as others. However, it's important and relevant even with JavaScript's lack of -type system. +JavaScript'in arayüzleri yoktur, bu nedenle bu ilke diğerleri kadar kesin olarak geçerli değildir. Bununla birlikte, JavaScript'in tür sistemi eksikliğinde bile önemli ve alâkalıdır. -ISP states that "Clients should not be forced to depend upon interfaces that -they do not use." Interfaces are implicit contracts in JavaScript because of -duck typing. +ISP, "kullanıcılar kullanmadığı arabirimlere bağımlı olmaya zorlanmamalıdır." der. Arabirimler, `Duck Typing` yüzünden JavaScript'de üstü kapalı anlaşmalardır. -A good example to look at that demonstrates this principle in JavaScript is for -classes that require large settings objects. Not requiring clients to setup -huge amounts of options is beneficial, because most of the time they won't need -all of the settings. Making them optional helps prevent having a -"fat interface". +Bu ilkeyi JavaScript'te gösteren iyi bir örnek, sınıflar büyük ayar nesneleri gerektirir. Kullanıcıların büyük miktarda seçenek ayarlamalarını istememek gerekli değildir, çünkü çoğu zaman tüm ayarlara ihtiyaç duymazlar. Bunları isteğe bağlı yapmak, bir "büyük arayüzü" olmasını önlemeye yardımcı olur. -**Bad:** +**Kötü:** ```javascript class DOMTraverser { @@ -1682,12 +1528,12 @@ class DOMTraverser { const $ = new DOMTraverser({ rootNode: document.getElementsByTagName("body"), - animationModule() {} // Most of the time, we won't need to animate when traversing. + animationModule() {} // Coğunlukla, bunu canlandırmamız gerekmeyecek // ... }); ``` -**Good:** +**İyi:** ```javascript class DOMTraverser { @@ -1721,32 +1567,24 @@ const $ = new DOMTraverser({ }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Dependency Inversion Principle (DIP) +### Bağlılığı Tersine Çevirme Prensibi (DIP) -This principle states two essential things: +Bu ilke iki temel şeyi ifade eder: -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. +1. Yüksek seviyeli modüller, düşük seviyeli modüllere bağlı olmamalıdır. Her ikisi de soyutlamalara bağlı olmalıdır. +2. Soyutlamalar detaylara bağlı olmamalıdır. Ayrıntılar soyutlamalara bağlı olmalıdır. -This can be hard to understand at first, but if you've worked with AngularJS, -you've seen an implementation of this principle in the form of Dependency -Injection (DI). While they are not identical concepts, DIP keeps high-level -modules from knowing the details of its low-level modules and setting them up. -It can accomplish this through DI. A huge benefit of this is that it reduces -the coupling between modules. Coupling is a very bad development pattern because -it makes your code hard to refactor. +İlk başta bunu anlamak zor olabilir, ancak AngularJS ile çalıştıysanız, bu prensibin Bağımlılık Enjeksiyonu (DI) şeklinde bir uygulamasını gördünüz. Aynı kavramlar olmasalar da, DIP yüksek seviyede modüllerin düşük seviyeli modüllerinin detaylarını bilmelerini ve ayarlamalarını sağlar. +Bunu DI ile başarabilir. Bunun büyük bir yararı, modüller arasındaki bağlantıyı azaltmasıdır. Eşleştirme(Coupling) çok kötü bir gelişme modelidir çünkü +kodunuzu yeniden düzenleme zorlaştırır. -As stated previously, JavaScript doesn't have interfaces so the abstractions -that are depended upon are implicit contracts. That is to say, the methods -and properties that an object/class exposes to another object/class. In the -example below, the implicit contract is that any Request module for an -`InventoryTracker` will have a `requestItems` method. +Daha önce belirtildiği gibi, JavaScript'in arayüzleri yoktur, bu nedenle soyutlamalar örtük sözleşmelere bağlıdır. +Yani, bir nesnenin / sınıfın başka bir nesneye / sınıfa maruz bıraktığı yöntemler ve özellikler. +Aşağıdaki örnekte, örtük sözleşme, bir `InventoryTracker` için herhangi bir Request modülünün `requestItems` yöntemine sahip olacağıdır. -**Bad:** +**Kötü:** ```javascript class InventoryRequester { @@ -1763,8 +1601,8 @@ class InventoryTracker { constructor(items) { this.items = items; - // BAD: We have created a dependency on a specific request implementation. - // We should just have requestItems depend on a request method: `request` + // KÖTÜ: Belirli bir istek uygulamasına bağımlılık yarattık. +    // requestItems sadece `request` 'e bağlımlı olmalıdır. this.requester = new InventoryRequester(); } @@ -1779,7 +1617,7 @@ const inventoryTracker = new InventoryTracker(["apples", "bananas"]); inventoryTracker.requestItems(); ``` -**Good:** +**İyi:** ```javascript class InventoryTracker { @@ -1815,8 +1653,8 @@ class InventoryRequesterV2 { } } -// By constructing our dependencies externally and injecting them, we can easily -// substitute our request module for a fancy new one that uses WebSockets. +// Bağımlılıklarımızı harici olarak yapılandırarak ve enjekte ederek +// istek modülümüzü WebSockets kullanan yeni ve havalı bir modülle kolayca değiştirebiliriz. const inventoryTracker = new InventoryTracker( ["apples", "bananas"], new InventoryRequesterV2() @@ -1824,28 +1662,19 @@ const inventoryTracker = new InventoryTracker( inventoryTracker.requestItems(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** + +## **Testler** -## **Testing** +Test etmek canlıya çıkmaktan bile önemlidir. Eğer testiniz yoksa veya yetersiz bir miktardaysa, kodu her gönderdiğinizde hiçbir şeyin bozulmadığına emin olmazsınız. Neyin yeterli bir miktar oluşturduğuna karar vermek takımınıza bağlıdır, %100 kapsama sahip olmak (tüm ifadeler ve şubeler) size güven ve gönül rahatlığı sağlar. Bu, harika bir test framework'üne sahip olmanın yanı sıra, [iyi bir kapsama aracı](https://gotwarlost.github.io/istanbul/) kullanmanız gerektiği anlamına gelir -Testing is more important than shipping. If you have no tests or an -inadequate amount, then every time you ship code you won't be sure that you -didn't break anything. Deciding on what constitutes an adequate amount is up -to your team, but having 100% coverage (all statements and branches) is how -you achieve very high confidence and developer peace of mind. This means that -in addition to having a great testing framework, you also need to use a -[good coverage tool](https://gotwarlost.github.io/istanbul/). +Test yazmamanın mazereti yoktur. Çok sayıda [iyi JS test framework'ü](https://jstherightway.org/#testing-tools) vardır, bu yüzden ekibinize uyan birini bulun. -There's no excuse to not write tests. There are [plenty of good JS test frameworks](https://jstherightway.org/#testing-tools), so find one that your team prefers. -When you find one that works for your team, then aim to always write tests -for every new feature/module you introduce. If your preferred method is -Test Driven Development (TDD), that is great, but the main point is to just -make sure you are reaching your coverage goals before launching any feature, -or refactoring an existing one. +Ekibiniz için uygun olanı bulduğunuzda, kullanılan her yeni özellik / modül için daima testler yazmayı hedefleyin. Tercih ettiğiniz yöntem Test Odaklı Geliştirme (TDD) ise, bu harika, ancak asıl mesele, herhangi bir özelliği başlatmadan veya mevcut bir özelliği yeniden düzenlemeden önce kapsama hedeflerinize ulaştığınızdan emin olmaktır. -### Single concept per test +### Her test için tek konsept -**Bad:** +**Kötü:** ```javascript import assert from "assert"; @@ -1869,7 +1698,7 @@ describe("MomentJS", () => { }); ``` -**Good:** +**İyi:** ```javascript import assert from "assert"; @@ -1895,16 +1724,15 @@ describe("MomentJS", () => { }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Concurrency** +## **Tutarlılık** -### Use Promises, not callbacks +### Promises kullanın, callback değil -Callbacks aren't clean, and they cause excessive amounts of nesting. With ES2015/ES6, -Promises are a built-in global type. Use them! +'Callback'ler temiz değildir ve aşırı miktarda iç içe geçmeye neden olurlar. ES2015 / ES6 ile Promise'ler yerleşik bir global tiptir. Onları kullan! -**Bad:** +**Kötü:** ```javascript import { get } from "request"; @@ -1928,7 +1756,7 @@ get( ); ``` -**Good:** +**İyi:** ```javascript import { get } from "request-promise"; @@ -1946,17 +1774,13 @@ get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Async/Await are even cleaner than Promises +### Async/Await kullanmak Promis kullanmaktan bile daha temiz -Promises are a very clean alternative to callbacks, but ES2017/ES8 brings async and await -which offer an even cleaner solution. All you need is a function that is prefixed -in an `async` keyword, and then you can write your logic imperatively without -a `then` chain of functions. Use this if you can take advantage of ES2017/ES8 features -today! +Promise'ler callback'lere göte çok daha temiz alternatiflerdir, ama ES2017/ES8 async ve await getirdi ve bu daha temiz bir çözüm sunuyor. Tek yapmanız gereken fonksiyonun başına `async` eklemek ve sonrasında mantıksal kullanımızı `then` zinciri kulanmadan yazabilirsiniz. Bugün ES2017 / ES8 özelliklerinden yararlanabiliyorsanız bunu kullanın! -**Bad:** +**Kötü:** ```javascript import { get } from "request-promise"; @@ -1974,7 +1798,7 @@ get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") }); ``` -**Good:** +**İyi:** ```javascript import { get } from "request-promise"; @@ -1995,25 +1819,21 @@ async function getCleanCodeArticle() { getCleanCodeArticle() ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** + +## **Hata Yönetimi** + +Atılan hatalar iyi bir şey! Bunlar, programınızdaki bir şey yanlış gittiğinde çalışma zamanının başarıyla tanımlandığı anlamına gelir ve sizi geçerli yığında (stack) fonksiyonu çalıştırmayı, işlevi dururup size konsolda yığın izlemede haber vererek yapar. -## **Error Handling** +--- HERE -Thrown errors are a good thing! They mean the runtime has successfully -identified when something in your program has gone wrong and it's letting -you know by stopping function execution on the current stack, killing the -process (in Node), and notifying you in the console with a stack trace. +### Yakalanmış hataları görmemezlikten gelmeyin -### Don't ignore caught errors +Yakalanan bir hatayla hiçbir şey yapmamanız size söz konusu hatayı düzeltebilme veya tepki gösterme yeteneği vermez. Hatayı konsola (`console.log`) kaydetmek, konsola yazdırılan bir şey denizinde kaybolabileceği sıklıkta daha iyi değildir. -Doing nothing with a caught error doesn't give you the ability to ever fix -or react to said error. Logging the error to the console (`console.log`) -isn't much better as often times it can get lost in a sea of things printed -to the console. If you wrap any bit of code in a `try/catch` it means you -think an error may occur there and therefore you should have a plan, -or create a code path, for when it occurs. +Herhangi bir kod parçasını `try/catch` içerisinde kullanıyorsanız, orada bir hata olabileceğini düşündüğünüz anlamına gelir ve bu nedenle gerçekleştiği zaman için bir planınız olması veya bir kod yolu oluşturmanız gerekir. -**Bad:** +**Kötü:** ```javascript try { @@ -2023,28 +1843,27 @@ try { } ``` -**Good:** +**İyi:** ```javascript try { functionThatMightThrow(); } catch (error) { - // One option (more noisy than console.log): + // Bir secenek (console.log'dan daha dikkat çekici) console.error(error); - // Another option: + // Bir secenek daha notifyUserOfError(error); - // Another option: + // Bir secenek daha reportErrorToService(error); - // OR do all three! + // veya hepsini bir yapın } ``` -### Don't ignore rejected promises +### Reddedilmiş promisleri görmemezlikten gelmeyin -For the same reason you shouldn't ignore caught errors -from `try/catch`. +Aynı sebeplerden dolayı, `try/catch`'de oluşan hataları yok saymamalısınız -**Bad:** +**Kötü:** ```javascript getdata() @@ -2056,7 +1875,7 @@ getdata() }); ``` -**Good:** +**İyi:** ```javascript getdata() @@ -2064,36 +1883,29 @@ getdata() functionThatMightThrow(data); }) .catch(error => { - // One option (more noisy than console.log): + // Bir secenek (console.log'dan daha dikkat çekici) console.error(error); - // Another option: + // Bir secenek daha notifyUserOfError(error); - // Another option: + // Bir secenek daha reportErrorToService(error); - // OR do all three! + // veya hepsini bir yapın }); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Formatting** +## **Biçimlendirme** -Formatting is subjective. Like many rules herein, there is no hard and fast -rule that you must follow. The main point is DO NOT ARGUE over formatting. -There are [tons of tools](https://standardjs.com/rules.html) to automate this. -Use one! It's a waste of time and money for engineers to argue over formatting. +Biçimlendirme özneldir. Buradaki birçok kural gibi, uygulamanız gereken zor ve hızlı bir kural yoktur. Ana nokta biçimlendirme üzerinde tartışma DEĞİLDİR. Bunu otomatikleştirmek için [tonlarca araç](https://standardjs.com/rules.html) vardır. Birini kullan! Mühendislerin biçimlendirme konusunda tartışmaları zaman ve para kaybıdır. -For things that don't fall under the purview of automatic formatting -(indentation, tabs vs. spaces, double vs. single quotes, etc.) look here -for some guidance. +Otomatik biçimlendirme (girintileme, sekmeler ve boşluklar, çift veya tek tırnak işaretleri vb.) Kapsamına girmeyen şeyler için bazı rehberlik için buraya bakın. -### Use consistent capitalization +### Tutarlı büyük harf kullanımı -JavaScript is untyped, so capitalization tells you a lot about your variables, -functions, etc. These rules are subjective, so your team can choose whatever -they want. The point is, no matter what you all choose, just be consistent. +JavaScript türsüzdür, bu nedenle büyük / küçük harf kullanımı değişkenleriniz, işlevleriniz vb. Hakkında çok şey anlatır. Bu kurallar özneldir, böylece ekibiniz istediklerini seçebilir. Mesele şu ki, ne seçerseniz seçin, tutarlı olun. -**Bad:** +**Kötü:** ```javascript const DAYS_IN_WEEK = 7; @@ -2109,7 +1921,7 @@ class animal {} class Alpaca {} ``` -**Good:** +**İyi:** ```javascript const DAYS_IN_WEEK = 7; @@ -2125,15 +1937,13 @@ class Animal {} class Alpaca {} ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Function callers and callees should be close +### Fonksion çağıranları ve çağrılanları yakın olmalı -If a function calls another, keep those functions vertically close in the source -file. Ideally, keep the caller right above the callee. We tend to read code from -top-to-bottom, like a newspaper. Because of this, make your code read that way. +Eğer bir fonksiyon diğer fonksiyonu çağırıyorsa, dikey olarak bu fonksiyonları kaynak dosyasında yakın tutun. İdeal olan, fonksiyonu kullanan kullandığı fonksiyonun hemen üstünde olmasıdır. We tend to read code from top-to-bottom, like a newspaper.Bu nedenle, kodunuzu bu şekilde okuyun. -**Bad:** +**Kötü:** ```javascript class PerformanceReview { @@ -2173,7 +1983,7 @@ const review = new PerformanceReview(employee); review.perfReview(); ``` -**Good:** +**İyi:** ```javascript class PerformanceReview { @@ -2213,37 +2023,37 @@ const review = new PerformanceReview(employee); review.perfReview(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## **Comments** +## **Yorumlar** -### Only comment things that have business logic complexity. +### Yalnızca iş mantığı karmaşıklığı olan şeyleri yorumlayın -Comments are an apology, not a requirement. Good code _mostly_ documents itself. +Yorumlar aslında bir özür, şart değil. İyi kod _çoğunlukla_ kendini belgelemektedir. -**Bad:** +**Kötü:** ```javascript function hashIt(data) { - // The hash + // Karma let hash = 0; - // Length of string + // String uzunluğu const length = data.length; - // Loop through every character in data + // Verilerdeki her karakteri gözden geçirin for (let i = 0; i < length; i++) { - // Get character code. + // Karakter kodunu al const char = data.charCodeAt(i); - // Make the hash + // Karıştır hash = (hash << 5) - hash + char; - // Convert to 32-bit integer + // 32-bit tam sayıya dönüştür hash &= hash; } } ``` -**Good:** +**İyi:** ```javascript function hashIt(data) { @@ -2254,19 +2064,19 @@ function hashIt(data) { const char = data.charCodeAt(i); hash = (hash << 5) - hash + char; - // Convert to 32-bit integer + // 32-bit tam sayıya dönüştür hash &= hash; } } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Don't leave commented out code in your codebase +### Kodlarınızı yorum olarak bırakmayın -Version control exists for a reason. Leave old code in your history. +Versiyon kontrol'un var olmasının bir sebebi var. Eski kodlarınızı tarihin tozlu sayfalarında bırakın. -**Bad:** +**Kötü:** ```javascript doStuff(); @@ -2275,20 +2085,19 @@ doStuff(); // doSoMuchStuff(); ``` -**Good:** +**İyi:** ```javascript doStuff(); ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Don't have journal comments +### Günlük yorumları yapmayın -Remember, use version control! There's no need for dead code, commented code, -and especially journal comments. Use `git log` to get history! +Hatırlayın, versiyon kontrol kullanın! Kullanılmayan koda, yoruma alınmış koda ve özellikle günlük kodlarına gerek yok. Geçmiş için `git log` kullanın. -**Bad:** +**Kötü:** ```javascript /** @@ -2302,7 +2111,7 @@ function combine(a, b) { } ``` -**Good:** +**İyi:** ```javascript function combine(a, b) { @@ -2310,14 +2119,13 @@ function combine(a, b) { } ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -### Avoid positional markers +### Yer belirleyicilerden kaçının -They usually just add noise. Let the functions and variable names along with the -proper indentation and formatting give the visual structure to your code. +Bunlar genellikle kirlilik yaratır. Fonksiyonların ve değişken adlarının yanı sıra uygun girinti ve biçimlendirme kodunuza görsel yapı kazandırsın. -**Bad:** +**Kötü:** ```javascript //////////////////////////////////////////////////////////////////////////////// @@ -2336,7 +2144,7 @@ const actions = function() { }; ``` -**Good:** +**İyi:** ```javascript $scope.model = { @@ -2349,11 +2157,11 @@ const actions = function() { }; ``` -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** -## Translation +## Çeviriler -This is also available in other languages: +Ayrıca diğer dillerde de: - ![am](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Armenia.png) **Armenian**: [hanumanum/clean-code-javascript/](https://github.com/hanumanum/clean-code-javascript) - ![bd](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bangladesh.png) **Bangla(বাংলা)**: [InsomniacSabbir/clean-code-javascript/](https://github.com/InsomniacSabbir/clean-code-javascript/) @@ -2377,4 +2185,4 @@ This is also available in other languages: - ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) -**[⬆ back to top](#table-of-contents)** +**[⬆ Başa dön](#İçindekiler)** From 46869c86bce8612bccf876b9b451f5e5890b8a4a Mon Sep 17 00:00:00 2001 From: Burak Sonmez Date: Sun, 29 Mar 2020 08:01:27 +0300 Subject: [PATCH 13/24] fix --- README.md | 902 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 547 insertions(+), 355 deletions(-) diff --git a/README.md b/README.md index d7747ff9..0bfe4c85 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,69 @@ # clean-code-javascript -## İçindekiler +## Table of Contents -1. [Giriş](#Giriş) -2. [Değişkenler](#Değişkenler) -3. [Fonksiyonlar](#Fonksiyonlar) -4. [Nesneler ve Veri Yapıları](#nesneler-ve-veri-yapıları) -5. [Sınıflar (Class)](#sınıflar) +1. [Introduction](#introduction) +2. [Variables](#variables) +3. [Functions](#functions) +4. [Objects and Data Structures](#objects-and-data-structures) +5. [Classes](#classes) 6. [SOLID](#solid) -7. [Testler](#testler) -8. [Tutarlılık](#Tutarlılık) -9. [Hata Yönetimi](#Hata-Yönetimi) -10. [Biçimlendirme](#Biçimlendirme) -11. [Yorumlar](#yorumlar) -12. [Çeviriler](#çeviriler) +7. [Testing](#testing) +8. [Concurrency](#concurrency) +9. [Error Handling](#error-handling) +10. [Formatting](#formatting) +11. [Comments](#comments) +12. [Translation](#translation) -## Giriş +## Introduction -![Kod okurken kaç defa bağıracağınızın bir sayısı olarak yazılım kalite tahmininin görüntüsü](https://www.osnews.com/images/comics/wtfm.jpg) +![Humorous image of software quality estimation as a count of how many expletives +you shout when reading code](https://www.osnews.com/images/comics/wtfm.jpg) -Robert C. Martin'nın kitabı olan ve yazılım mühendisliği ilkerini barındıran [_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)'un JavaScript için uyarlanmış hali. Bu bir tarz rehberi değil. JavaScript'te [okunabilir, yeniden kullanılabilir ve yeniden düzenlenebilir](https://github.com/ryanmcdermott/3rs-of-software-architecture) yazılımlar üretmeye yönelik bir kılavuzdur. +Software engineering principles, from Robert C. Martin's book +[_Clean Code_](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882), +adapted for JavaScript. This is not a style guide. It's a guide to producing +[readable, reusable, and refactorable](https://github.com/ryanmcdermott/3rs-of-software-architecture) software in JavaScript. -Buradaki her ilkeye kesinlikle uyulmak zorunda değildir ve daha azı evrensel olarak kabul edilecektir. Bunlar önerilerden başka bir şey değildir, fakat bunlar _Clean Code_ yazarları tarafından uzun yıllar süren tecrübeler ile kodlandı. +Not every principle herein has to be strictly followed, and even fewer will be +universally agreed upon. These are guidelines and nothing more, but they are +ones codified over many years of collective experience by the authors of +_Clean Code_. -Yazılım mühendisliği zanaatımız 50 yaşın biraz üzerinde ve hala çok şey öğreniyoruz. Yazılım mimarisi, mimarinin kendisi kadar eski olduğunda, belki de takip edilmesi daha zor kurallarımız olacak. Şimdi, bu önerilerin sizin ve ekibinizin ürettiği JavaScript kodunun kalitesini değerlendirmek için bir mihenk taşı işlevi görmesine izin verin. +Our craft of software engineering is just a bit over 50 years old, and we are +still learning a lot. When software architecture is as old as architecture +itself, maybe then we will have harder rules to follow. For now, let these +guidelines serve as a touchstone by which to assess the quality of the +JavaScript code that you and your team produce. -Bir şey daha: bunların bilinmesi sizi hemen daha iyi bir yazılım geliştiricisi yapmaz ve uzun yıllar onlarla çalışmak hata yapmayacağınız anlamına gelmez. +One more thing: knowing these won't immediately make you a better software +developer, and working with them for many years doesn't mean you won't make +mistakes. Every piece of code starts as a first draft, like wet clay getting +shaped into its final form. Finally, we chisel away the imperfections when +we review it with our peers. Don't beat yourself up for first drafts that need +improvement. Beat up the code instead! -Her kod parçası ilk taslak olarak başlar, örneğin ıslak kil son halini alır. Son olarak, akranlarımızla gözden geçirdiğimizde kusurları kesiyoruz. İyileştirilmesi gereken ilk taslaklar için kendinize yüklenmeyin. Onun yerine kodunuza yüklenin. +## **Variables** -## **Değişkenler** +### Use meaningful and pronounceable variable names -### Anlamlı ve belirgin değişken adları kullanın - -**Kötü:** +**Bad:** ```javascript const yyyymmdstr = moment().format("YYYY/MM/DD"); ``` -**İyi:** +**Good:** ```javascript const currentDate = moment().format("YYYY/MM/DD"); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Aynı değişken türü için aynı kelimeleri kullanın +### Use the same vocabulary for the same type of variable -**Kötü:** +**Bad:** ```javascript getUserInfo(); @@ -57,41 +71,45 @@ getClientData(); getCustomerRecord(); ``` -**İyi:** +**Good:** ```javascript getUser(); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Aranabilir isimler kullanın +### Use searchable names -Yazacağımızdan daha fazla kod okuyacağız. Yazdığımız kodun okunabilir ve aranabilir olması önemlidir. Değişkenleri anlamlı ve anlaşılabilir _isimlendirmemekle_, okuyucuya zarar veriyoruz. -Adlarınızı aranabilir hale getirin. [buddy.js](https://github.com/danielstjules/buddy.js) ve -[ESLint](https://github.com/eslint/eslint/blob/660e0918933e6e7fede26bc675a0763a6b357c94/docs/rules/no-magic-numbers.md) gibi araçlar isimlendirilmemiş sabitlerinizi belirlemenize yardımcı olacaktır. +We will read more code than we will ever write. It's important that the code we +do write is readable and searchable. By _not_ naming variables that end up +being meaningful for understanding our program, we hurt our readers. +Make your names searchable. Tools like +[buddy.js](https://github.com/danielstjules/buddy.js) and +[ESLint](https://github.com/eslint/eslint/blob/660e0918933e6e7fede26bc675a0763a6b357c94/docs/rules/no-magic-numbers.md) +can help identify unnamed constants. -**Kötü:** +**Bad:** ```javascript -// 86400000 neydi ? +// What the heck is 86400000 for? setTimeout(blastOff, 86400000); ``` -**İyi:** +**Good:** ```javascript -// Bunları büyük harfle adlandırılmış sabitler olarak bildirin. +// Declare them as capitalized named constants. const MILLISECONDS_IN_A_DAY = 86_400_000; setTimeout(blastOff, MILLISECONDS_IN_A_DAY); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Açıklayıcı değişkenler kullan +### Use explanatory variables -**Kötü:** +**Bad:** ```javascript const address = "One Infinite Loop, Cupertino 95014"; @@ -102,7 +120,7 @@ saveCityZipCode( ); ``` -**İyi:** +**Good:** ```javascript const address = "One Infinite Loop, Cupertino 95014"; @@ -111,13 +129,13 @@ const [_, city, zipCode] = address.match(cityZipCodeRegex) || []; saveCityZipCode(city, zipCode); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Kafadan planmaktan kaçının +### Avoid Mental Mapping -Açık olmak, ima etmekten iyidir. +Explicit is better than implicit. -**Kötü:** +**Bad:** ```javascript const locations = ["Austin", "New York", "San Francisco"]; @@ -127,12 +145,12 @@ locations.forEach(l => { // ... // ... // ... - // Bir dakika, 'l' neydi? + // Wait, what is `l` for again? dispatch(l); }); ``` -**İyi:** +**Good:** ```javascript const locations = ["Austin", "New York", "San Francisco"]; @@ -146,13 +164,14 @@ locations.forEach(location => { }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Gereksiz içerikler eklemeyin +### Don't add unneeded context -Sınıf / nesne adınız size bir şey söylüyorsa, bunu değişken adınızda tekrarlamayın. +If your class/object name tells you something, don't repeat that in your +variable name. -**Kötü:** +**Bad:** ```javascript const Car = { @@ -166,7 +185,7 @@ function paintCar(car) { } ``` -**İyi:** +**Good:** ```javascript const Car = { @@ -180,13 +199,16 @@ function paintCar(car) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Kısa devre veya şartlar yerine önceden tanımlanmış argümanlar kullanın +### Use default arguments instead of short circuiting or conditionals -Önceden tanımlanan argümanlar genellikle kısa devrelere göre daha temizdir. Bunları kullanırsanız şunun farkında olun, fonksiyonunuz sadece `tanımsız` _(undefined)_ değerler için önceden tanımlanmış argümana kullanacaktır. `''`, `""`, `false`, `null`, `0`, ve `NaN` gibi "yanlış denilebilecek" değerler önceden tanımlanmış bir değerle değiştirilmez. +Default arguments are often cleaner than short circuiting. Be aware that if you +use them, your function will only provide default values for `undefined` +arguments. Other "falsy" values such as `''`, `""`, `false`, `null`, `0`, and +`NaN`, will not be replaced by a default value. -**Kötü:** +**Bad:** ```javascript function createMicrobrewery(name) { @@ -195,7 +217,7 @@ function createMicrobrewery(name) { } ``` -**İyi:** +**Good:** ```javascript function createMicrobrewery(name = "Hipster Brew Co.") { @@ -203,27 +225,41 @@ function createMicrobrewery(name = "Hipster Brew Co.") { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Fonksiyonlar** +## **Functions** -### Fonksiyonlar argümanları (Tercihen 2 veya daha az) +### Function arguments (2 or fewer ideally) -Fonksiyon parametrelerinin sayısını sınırlamak inanılmaz derecede önemlidir, çünkü fonksiyonunuzu test etmeyi kolaylaştırır. Üçten fazlasına sahip olmak, her bir argümanla tonlarca farklı vakayı test etmeniz gereken bir kombinasyonel patlamaya yol açar. +Limiting the amount of function parameters is incredibly important because it +makes testing your function easier. Having more than three leads to a +combinatorial explosion where you have to test tons of different cases with +each separate argument. -Bir veya iki argüman ideal durumdur ve mümkünse üç tanesinden kaçınılmalıdır. Bundan daha fazlası birleştirilmeldir. Genellikle, -ikiden fazla argüman sonra fonksiyonunuz çok işlem yapmaya çalışıyor. Olmadığı durumlarda, çoğu zaman daha üst düzey bir nesne argüman olarak yeterli olacaktır. +One or two arguments is the ideal case, and three should be avoided if possible. +Anything more than that should be consolidated. Usually, if you have +more than two arguments then your function is trying to do too much. In cases +where it's not, most of the time a higher-level object will suffice as an +argument. -JavaScript havada nesne yapmanıza olanak sağladığı için, bir çok sınıf yapısına gerek kalmadan, bir nesneyi birden fazla nesne kullanmadan kullanabilirsiniz. +Since JavaScript allows you to make objects on the fly, without a lot of class +boilerplate, you can use an object if you are finding yourself needing a +lot of arguments. -Fonksiyonun hangi özellikleri beklediğini netleştirmek için ES2015 / ES6 ayrıştırma sintaksını kullanabilirsiniz. Bunun birkaç avantajı vardır: +To make it obvious what properties the function expects, you can use the ES2015/ES6 +destructuring syntax. This has a few advantages: -1. Birisi fonksiyonun imzasına baktığında, hangi özelliklerin kullanıldığını hemen anlar.. -2. Adlandırılmış parametreleri simüle etmek için kullanılabilir. -3. Ayrıştırma işlemi ayrıca fonksiyona iletilen argüman nesnesinin belirtilen ilk değerlerini de klonlar. Bu, yan etkilerin önlenmesine yardımcı olabilir. Not: Argüman nesnelerinden ayrıştırılan nesneler ve diziler klonlanmaz! -4. Linters, sizi kullanılmayan değerler için uyarabilir bu da ayrıştırmadan imkansız olurdu. +1. When someone looks at the function signature, it's immediately clear what + properties are being used. +2. It can be used to simulate named parameters. +3. Destructuring also clones the specified primitive values of the argument + object passed into the function. This can help prevent side effects. Note: + objects and arrays that are destructured from the argument object are NOT + cloned. +4. Linters can warn you about unused properties, which would be impossible + without destructuring. -**Kötü:** +**Bad:** ```javascript function createMenu(title, body, buttonText, cancellable) { @@ -234,7 +270,7 @@ createMenu("Foo", "Bar", "Baz", true); ``` -**İyi:** +**Good:** ```javascript function createMenu({ title, body, buttonText, cancellable }) { @@ -249,13 +285,17 @@ createMenu({ }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksiyonlar bir şey yapmalı +### Functions should do one thing -Bu, yazılım mühendisliğinde açık ara en önemli kuraldır. Fonksiyonlar birden fazla şey yaptığında, birleştirmesi, test etmesi ve anlamdırılması daha zordur. Bir fonksiyonu yalnızca bir eyleme ayırabildiğinizde, kolayca yeniden düzenlenebilir ve kodunuz çok daha temiz okunur. Bu yazıdan başka bir şey almazsanız dahi sadece bununla birçok geliştiricinin önünde olacaksınız. +This is by far the most important rule in software engineering. When functions +do more than one thing, they are harder to compose, test, and reason about. +When you can isolate a function to just one action, it can be refactored +easily and your code will read much cleaner. If you take nothing else away from +this guide other than this, you'll be ahead of many developers. -**Kötü:** +**Bad:** ```javascript function emailClients(clients) { @@ -268,7 +308,7 @@ function emailClients(clients) { } ``` -**İyi:** +**Good:** ```javascript function emailActiveClients(clients) { @@ -281,11 +321,11 @@ function isActiveClient(client) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksiyon isimleri ne yaptıklarını anlatmalı +### Function names should say what they do -**Kötü:** +**Bad:** ```javascript function addToDate(date, month) { @@ -294,11 +334,11 @@ function addToDate(date, month) { const date = new Date(); -// Fonksiyonun adından ne eklendiğini söylemek zor +// It's hard to tell from the function name what is added addToDate(date, 1); ``` -**İyi:** +**Good:** ```javascript function addMonthToDate(month, date) { @@ -309,13 +349,15 @@ const date = new Date(); addMonthToDate(1, date); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksiyonlar soyutlaştırmadan sadece bir seviye uzak olmalıdır +### Functions should only be one level of abstraction -Birden fazla soyutlama seviyeniz olduğunda fonksiyonunuz genellikle çok fazla şey yapar. Fonksiyonların bölünmesi, yeniden kullanılabilirliği ve daha kolay test yapılmasını sağlayacak. +When you have more than one level of abstraction your function is usually +doing too much. Splitting up functions leads to reusability and easier +testing. -**Kötü:** +**Bad:** ```javascript function parseBetterJSAlternative(code) { @@ -342,7 +384,7 @@ function parseBetterJSAlternative(code) { } ``` -**İyi:** +**Good:** ```javascript function parseBetterJSAlternative(code) { @@ -379,19 +421,32 @@ function parse(tokens) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Tekrarlanan kodu sil +### Remove duplicate code -Tekrarlanan kodlardan kaçınmak için elinizden geleni yapın. Tekrarlanan kod kötü çünkü bazı mantığı değiştirmeniz gerekirse bir şeyi değiştirmek için birden fazla yer olduğu anlamına geliyor. +Do your absolute best to avoid duplicate code. Duplicate code is bad because it +means that there's more than one place to alter something if you need to change +some logic. -Bir restoran işlettiğinizi ve stoklarınızı takip ettiğinizi düşünün: tüm domates, soğan, sarımsak, baharat, vb. onlara. Yalnızca bir listeniz varsa, güncellenecek tek bir yer vardır! +Imagine if you run a restaurant and you keep track of your inventory: all your +tomatoes, onions, garlic, spices, etc. If you have multiple lists that +you keep this on, then all have to be updated when you serve a dish with +tomatoes in them. If you only have one list, there's only one place to update! -Çoğunlukla yinelenen kodunuz vardır, çünkü çoğu şeyi ortak paylaşsalar dahi çok küçük bir kaç farklılık vardır, ancak farklılıkları sizi aynı şeylerin çoğunu yapan iki veya daha fazla ayrı fonksiyona sahip olmaya zorlar. Tekrarlanan kodun kaldırılması, bu farklı şeyleri tek bir fonksiyon / modül / sınıfla işleyebilecek bir soyutlama oluşturmak anlamına gelir. +Oftentimes you have duplicate code because you have two or more slightly +different things, that share a lot in common, but their differences force you +to have two or more separate functions that do much of the same things. Removing +duplicate code means creating an abstraction that can handle this set of +different things with just one function/module/class. -Soyutlamayı doğru yapmak kritik öneme sahiptir, bu yüzden _Sınıflar_ bölümünde belirtilen SOLID ilkelerini izlemelisiniz. Kötü soyutlamalar yinelenen koddan daha kötü olabilir, bu yüzden dikkatli olun! Bunu söyledikten sonra, eğer iyi bir soyutlama yapabilirseniz, yapın! Kendinizi tekrarlamayın, aksi takdirde bir şeyi değiştirmek istediğinizde kendinizi birden fazla yeri güncellerken bulacaksınız. +Getting the abstraction right is critical, that's why you should follow the +SOLID principles laid out in the _Classes_ section. Bad abstractions can be +worse than duplicate code, so be careful! Having said this, if you can make +a good abstraction, do it! Don't repeat yourself, otherwise you'll find yourself +updating multiple places anytime you want to change one thing. -**Kötü:** +**Bad:** ```javascript function showDeveloperList(developers) { @@ -425,7 +480,7 @@ function showManagerList(managers) { } ``` -**İyi:** +**Good:** ```javascript function showEmployeeList(employees) { @@ -452,11 +507,11 @@ function showEmployeeList(employees) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Object.assign ile varsayılan nesneleri ayarlama +### Set default objects with Object.assign -**Kötü:** +**Bad:** ```javascript const menuConfig = { @@ -477,12 +532,12 @@ function createMenu(config) { createMenu(menuConfig); ``` -**İyi:** +**Good:** ```javascript const menuConfig = { title: "Order", - // Kullanıcı 'body' eklemedi + // User did not include 'body' key buttonText: "Send", cancellable: true }; @@ -498,20 +553,20 @@ function createMenu(config) { config ); - // config çıktısı şimdi : {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} + // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true} // ... } createMenu(menuConfig); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksiyon parametrelerinde işaretleme kullanma +### Don't use flags as function parameters -İşaretlemeler fonksiyonunuzun birden fazla şey yaptığını gösterir. Fonkisyonlar sadece tek şey yapmalılar. Eğer aşağıdakine benzer değişiklere ve mantıksal operatorlere sahip fonksiyonunuz varsa fonksiyonlarınızı ayırın. +Flags tell your user that this function does more than one thing. Functions should do one thing. Split out your functions if they are following different code paths based on a boolean. -**Kötü:** +**Bad:** ```javascript function createFile(name, temp) { @@ -523,7 +578,7 @@ function createFile(name, temp) { } ``` -**İyi:** +**Good:** ```javascript function createFile(name) { @@ -535,21 +590,30 @@ function createTempFile(name) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yan Etkilerden Kaçının (Bölüm 1) +### Avoid Side Effects (part 1) -Bir fonksiyon, bir değeri alıp başka bir değer veya değer döndürmekten başka bir şey yaparsa yan etki üretir. Bir yan etki, bir dosyaya yazma, bazı global değişkeni değiştirme veya yanlışlıkla tüm paranızı bir yabancıya gönderme olabilir. +A function produces a side effect if it does anything other than take a value in +and return another value or values. A side effect could be writing to a file, +modifying some global variable, or accidentally wiring all your money to a +stranger. -Şimdi, zaman zaman bir programda yan etkilere sahip olmanız gerekir. Önceki örnekte olduğu gibi, bir dosyaya yazmanız gerekebilir. Yapmak istediğiniz, bunu yapacağınız yeri merkezileştirmektir. Birden fazla yazma işlemi yapan fonksiyonlar veya sınıflar yapmayın. Bunu yapan bir servisiniz olsun. Bir ve sadece bir. +Now, you do need to have side effects in a program on occasion. Like the previous +example, you might need to write to a file. What you want to do is to +centralize where you are doing this. Don't have several functions and classes +that write to a particular file. Have one service that does it. One and only one. -Buradaki ana nokta, herhangi bir yapıya sahip olmayan nesneler arasında durumu(state) paylaşmak, herhangi bir şeyle yazılabilen değiştirilebilir(mutable) veri türlerini kullanmak ve yan etkilerinizin nerede ortaya çıktığını merkezileştirmemek gibi yaygın tuzaklardan kaçınmaktır. Bunu yapabilirseniz, diğer programcıların büyük çoğunluğundan daha mutlu olacaksınız. +The main point is to avoid common pitfalls like sharing state between objects +without any structure, using mutable data types that can be written to by anything, +and not centralizing where your side effects occur. If you can do this, you will +be happier than the vast majority of other programmers. -**Kötü:** +**Bad:** ```javascript -// Aşağıdaki fonksiyon Global değişkeni refere alıyor -// Bu adı kullanan başka bir fonksiyonumuz olsaydı, şimdi bir dizi olurdu ve onu bozacaktı. +// Global variable referenced by following function. +// If we had another function that used this name, now it'd be an array and it could break it. let name = "Ryan McDermott"; function splitIntoFirstAndLastName() { @@ -561,7 +625,7 @@ splitIntoFirstAndLastName(); console.log(name); // ['Ryan', 'McDermott']; ``` -**İyi:** +**Good:** ```javascript function splitIntoFirstAndLastName(name) { @@ -575,27 +639,44 @@ console.log(name); // 'Ryan McDermott'; console.log(newName); // ['Ryan', 'McDermott']; ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yan Etkilerden Kaçının (Bölüm 2) +### Avoid Side Effects (part 2) -JavaScript'te, temel öğeler değerlerle aktarılır (passed by value) ve objeler/diziler referans ile aktarılır (passed by reference). +In JavaScript, primitives are passed by value and objects/arrays are passed by +reference. In the case of objects and arrays, if your function makes a change +in a shopping cart array, for example, by adding an item to purchase, +then any other function that uses that `cart` array will be affected by this +addition. That may be great, however it can be bad too. Let's imagine a bad +situation: -Bu durumda, nesnelerde ve dizilerde fonksiyonunuz bir değişiklik yaparsa -örneğin, bir alışveriş sepeti dizisinde, satın almak için bir öğe ekleyerek, -bu `cart` dizisini kullanan diğer fonksiyonlar bu eklemeden etkilenecektir. -Bu harika olabilir, ancak kötü de olabilir. Kötü bir hayal edelim -durum: +The user clicks the "Purchase" button which calls a `purchase` function that +spawns a network request and sends the `cart` array to the server. Because +of a bad network connection, the `purchase` function has to keep retrying the +request. Now, what if in the meantime the user accidentally clicks "Add to Cart" +button on an item they don't actually want before the network request begins? +If that happens and the network request begins, then that purchase function +will send the accidentally added item because it has a reference to a shopping +cart array that the `addItemToCart` function modified by adding an unwanted +item. -Kullanıcı, 'Satın Al' butonuna basar ve bu `satınal` fonksiyonu sunucuya bir istek atarak `sepet` dizisini sunucuya gönderir. Kötü bir ağ bağlantısı nedeniyle, `satınal` işlevi isteği yeniden denemeye devam etmelidir. Şimdi, bu arada kullanıcı yanlışlıkla ağ isteği başlamadan istemedikleri bir öğenin üzerine "Sepete Ekle" düğmesini tıklarsa ne olur? Bu olursa ve ağ isteği başlarsa, yanlışlıkla satın alınan öğeyi gönderir çünkü alışveriş sepeti dizisine, `ürünüSepeteEkle` işlevinin istenmeyen bir öğe ekleyerek değiştirdiği bir referansı vardır. `ürünüSepeteEkle` ın her zaman `sepeti` klonlaması, düzenlemesi ve klonu döndürmesi için harika bir çözüm olacaktır. Bu, alışveriş sepetinin referansını tutan başka hiçbir işlevin herhangi bir değişiklikten etkilenmemesini sağlar. +A great solution would be for the `addItemToCart` to always clone the `cart`, +edit it, and return the clone. This ensures that no other functions that are +holding onto a reference of the shopping cart will be affected by any changes. -Bu yaklaşıma değinecek iki uyarı: +Two caveats to mention to this approach: -1. Girilen nesnesini gerçekten değiştirmek istediğiniz durumlar olabilir, ancak bunu uyguladığınızda, bu vakaların oldukça nadir olduğunu göreceksiniz. Çoğu şeyin yan etkisi olmayacak şekilde yeniden düzenlenebilir! +1. There might be cases where you actually want to modify the input object, + but when you adopt this programming practice you will find that those cases + are pretty rare. Most things can be refactored to have no side effects! -2. Büyük nesneleri klonlamak performans açısından çok pahalı olabilir. Neyse ki, bu pratikte büyük bir sorun değildir, çünkü bu tür programlama yaklaşımlarını manuel yapmaktansa daha hızlı olmasını ve büyük nesneleri ve dizileri klonlanlarken daha az bellek harcayan [harika kütüphaneler](https://facebook.github.io/immutable-js/) vardır. +2. Cloning big objects can be very expensive in terms of performance. Luckily, + this isn't a big issue in practice because there are + [great libraries](https://facebook.github.io/immutable-js/) that allow + this kind of programming approach to be fast and not as memory intensive as + it would be for you to manually clone objects and arrays. -**Kötü:** +**Bad:** ```javascript const addItemToCart = (cart, item) => { @@ -603,7 +684,7 @@ const addItemToCart = (cart, item) => { }; ``` -**İyi:** +**Good:** ```javascript const addItemToCart = (cart, item) => { @@ -611,17 +692,21 @@ const addItemToCart = (cart, item) => { }; ``` -**[⬆ Başa dön](#İçindekiler)** - -### Global fonksiyonlar yazma +**[⬆ back to top](#table-of-contents)** -Globalleri kirletmek JavaScript'te kötü bir uygulamadır, çünkü başka bir kütüphaneyle çakıştırabilirsiniz ve API'lerinizi kullananlar kişiler canlıya çıkana kadar bu aksi durumların farkında olmayabilir. +### Don't write to global functions -Bir örnek düşünelim: JavaScript'in yerel kütüphanesindeki dizi `diff` methodunu genişletmek ve iki dizinin farklılıklarını göstermek istediğinizi var sayalım. JavaScript'in yerel Array yöntemini iki dizi arasındaki farkı gösterebilecek bir "diff" yöntemine genişletmek mi istiyorsunuz? +Polluting globals is a bad practice in JavaScript because you could clash with another +library and the user of your API would be none-the-wiser until they get an +exception in production. Let's think about an example: what if you wanted to +extend JavaScript's native Array method to have a `diff` method that could +show the difference between two arrays? You could write your new function +to the `Array.prototype`, but it could clash with another library that tried +to do the same thing. What if that other library was just using `diff` to find +the difference between the first and last elements of an array? This is why it +would be much better to just use ES2015/ES6 classes and simply extend the `Array` global. -Yeni fonksiyonunuzu `Array.prototype`'e yazabilirsiniz, ancak aynı şeyi yapmaya çalışan başka bir kütüphane ile çakışabilir. Ya diğer kütüphane bir dizinin ilk ve son elemanları arasındaki farkı bulmak için sadece `diff` kullanıyorsa? Bu yüzden sadece ES2015 / ES6 sınıflarını kullanmak ve `Array` globalini genişletmek çok daha iyi olurdu. - -**Kötü:** +**Bad:** ```javascript Array.prototype.diff = function diff(comparisonArray) { @@ -630,7 +715,7 @@ Array.prototype.diff = function diff(comparisonArray) { }; ``` -**İyi:** +**Good:** ```javascript class SuperArray extends Array { @@ -641,13 +726,15 @@ class SuperArray extends Array { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Zorunlu programlama yerine fonksiyonel programlamayı tercih edin +### Favor functional programming over imperative programming -JavaScript, Haskell'in olduğu gibi işlevsel bir dil değildir, ancak işlevsel bir tadı vardır. İşlevsel diller daha temiz ve test edilmesi daha kolay olabilir. Yapabildiğinizde bu tarz bir programlama yapın. +JavaScript isn't a functional language in the way that Haskell is, but it has +a functional flavor to it. Functional languages can be cleaner and easier to test. +Favor this style of programming when you can. -**Kötü:** +**Bad:** ```javascript const programmerOutput = [ @@ -676,7 +763,7 @@ for (let i = 0; i < programmerOutput.length; i++) { } ``` -**İyi:** +**Good:** ```javascript const programmerOutput = [ @@ -704,11 +791,11 @@ const totalOutput = programmerOutput.reduce( ); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Koşulları kapsamak +### Encapsulate conditionals -**Kötü:** +**Bad:** ```javascript if (fsm.state === "fetching" && isEmpty(listNode)) { @@ -716,7 +803,7 @@ if (fsm.state === "fetching" && isEmpty(listNode)) { } ``` -**İyi:** +**Good:** ```javascript function shouldShowSpinner(fsm, listNode) { @@ -728,11 +815,11 @@ if (shouldShowSpinner(fsmInstance, listNodeInstance)) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** ### Avoid negative conditionals -**Kötü:** +**Bad:** ```javascript function isDOMNodeNotPresent(node) { @@ -744,7 +831,7 @@ if (!isDOMNodeNotPresent(node)) { } ``` -**İyi:** +**Good:** ```javascript function isDOMNodePresent(node) { @@ -756,14 +843,20 @@ if (isDOMNodePresent(node)) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Koşullardan kaçının +### Avoid conditionals -Bu imkansız bir görev gibi görünüyor. Bunu ilk kez duyduktan sonra, çoğu kişi "`if` ifadesi olmadan nasıl bir şey yapmam gerekiyor?" Cevap şu ki -birçok durumda aynı görevi yerine getirmek için polimorfizm kullanabilirsiniz. İkinci soru genellikle, "peki bu harika ama neden bunu yapmak isteyeyim ki?" Cevap, daha önce öğrendiğimiz temiz bir kod kavramıydı: bir fonksiyon sadece bir şey yapmalı. `If` ifadeleri olan sınıflarınız ve fonksiyonlarınız olduğunda, kullanıcılara işlevinizin birden fazla şey yaptığını söylüyor. Unutmayın, sadece bir şey yapın. +This seems like an impossible task. Upon first hearing this, most people say, +"how am I supposed to do anything without an `if` statement?" The answer is that +you can use polymorphism to achieve the same task in many cases. The second +question is usually, "well that's great but why would I want to do that?" The +answer is a previous clean code concept we learned: a function should only do +one thing. When you have classes and functions that have `if` statements, you +are telling your user that your function does more than one thing. Remember, +just do one thing. -**Kötü:** +**Bad:** ```javascript class Airplane { @@ -781,7 +874,7 @@ class Airplane { } ``` -**İyi:** +**Good:** ```javascript class Airplane { @@ -810,13 +903,16 @@ class Cessna extends Airplane { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yazım denetiminden kaçının (Bölüm 1) +### Avoid type-checking (part 1) -JavaScript türsüzdür, yani işlevleriniz her türlü argümanı alabilir. Bazen bu özgürlük bizi oltaya getirebilir ve fonksiyonlarınızda tip kontrolü yapmak cazip hale gelir. Bunu yapmaktan kaçınmanın birçok yolu vardır. Dikkate alınması gereken ilk şey tutarlı API'lardır. +JavaScript is untyped, which means your functions can take any type of argument. +Sometimes you are bitten by this freedom and it becomes tempting to do +type-checking in your functions. There are many ways to avoid having to do this. +The first thing to consider is consistent APIs. -**Kötü:** +**Bad:** ```javascript function travelToTexas(vehicle) { @@ -828,7 +924,7 @@ function travelToTexas(vehicle) { } ``` -**İyi:** +**Good:** ```javascript function travelToTexas(vehicle) { @@ -836,14 +932,21 @@ function travelToTexas(vehicle) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yazım denetiminden kaçının (Bölüm 2) +### Avoid type-checking (part 2) -Dizeler ve tamsayılar gibi temel ilkel değerlerle çalışıyorsanız, -ve polimorfizm kullanamazsınız, ancak yine de yazım denetimi yapma gereğini hissediyorsanız, TypeScript kullanmayı düşünmelisiniz. Standart JavaScript sentaks üstünde statik yazım sağladığı için normal JavaScript'e mükemmel bir alternatiftir. Manuel olarak normal JavaScript'i kontrol etmeyle ilgili sorun, iyi yapmak o kadar fazla ayrıntılı gerektirir ki, elde ettiğiniz sahte "tip güvenliği" kaybettiğiniz okunabilirliği telafi etmez. JavaScript'inizi temiz tutun, iyi testler yazın ve iyi kod incelemelerine sahip olun. Aksi takdirde, hepsini TypeScript ile yapın (dediğim gibi harika bir alternatif!). +If you are working with basic primitive values like strings and integers, +and you can't use polymorphism but you still feel the need to type-check, +you should consider using TypeScript. It is an excellent alternative to normal +JavaScript, as it provides you with static typing on top of standard JavaScript +syntax. The problem with manually type-checking normal JavaScript is that +doing it well requires so much extra verbiage that the faux "type-safety" you get +doesn't make up for the lost readability. Keep your JavaScript clean, write +good tests, and have good code reviews. Otherwise, do all of that but with +TypeScript (which, like I said, is a great alternative!). -**Kötü:** +**Bad:** ```javascript function combine(val1, val2) { @@ -858,7 +961,7 @@ function combine(val1, val2) { } ``` -**İyi:** +**Good:** ```javascript function combine(val1, val2) { @@ -866,25 +969,27 @@ function combine(val1, val2) { } ``` -**[⬆ Başa dön](#İçindekiler)** - -### Aşırı optimizasyon yapma +**[⬆ back to top](#table-of-contents)** -Modern tarayıcılar çalışma zamanında çok sayıda optimizasyon yapar. Çoğu zaman, eğer optimize ediyorsanız, sadece zamanınızı boşa harcıyorsunuz demektir. +### Don't over-optimize -Optimizasyonun nerede olmadığını görmek için [iyi kaynaklar](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) vardır. Bunları optimize edene kadar işaretleyebilirsiniz. +Modern browsers do a lot of optimization under-the-hood at runtime. A lot of +times, if you are optimizing then you are just wasting your time. [There are good +resources](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) +for seeing where optimization is lacking. Target those in the meantime, until +they are fixed if they can be. -**Kötü:** +**Bad:** ```javascript -// Eski tarayıcılarda, önbelleğe alınmamış "list.length" içeren her yineleme maliyetli olacaktır -// list.length yeniden hesaplanması nedeniyle. Modern tarayıcılarda bu optimize edilmiştir. +// On old browsers, each iteration with uncached `list.length` would be costly +// because of `list.length` recomputation. In modern browsers, this is optimized. for (let i = 0, len = list.length; i < len; i++) { // ... } ``` -**İyi:** +**Good:** ```javascript for (let i = 0; i < list.length; i++) { @@ -892,13 +997,15 @@ for (let i = 0; i < list.length; i++) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Kullanılmayan kodları silin +### Remove dead code -Ölü kod, yinelenen kod kadar kötü. Kod tabanınızda tutmak için bir neden yoktur. Eğer çağrılmazsa, ondan kurtulun! Hala ihtiyacınız varsa sürüm geçmişinizde güvende olacaktır. +Dead code is just as bad as duplicate code. There's no reason to keep it in +your codebase. If it's not being called, get rid of it! It will still be safe +in your version history if you still need it. -**Kötü:** +**Bad:** ```javascript function oldRequestModule(url) { @@ -913,7 +1020,7 @@ const req = newRequestModule; inventoryTracker("apples", req, "www.inventory-awesome.io"); ``` -**İyi:** +**Good:** ```javascript function newRequestModule(url) { @@ -924,21 +1031,25 @@ const req = newRequestModule; inventoryTracker("apples", req, "www.inventory-awesome.io"); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Nesneler ve Veri Yapıları** +## **Objects and Data Structures** -### Alıcıları ve ayarlayıcıları kullanma (Getters & Setters) +### Use getters and setters -Nesnelerdeki verilere erişmek için alıcıları ve ayarlayıcıları kullanmak, bir nesnedeki bir özelliği aramaktan daha iyi olabilir. "Neden?" sorabilirsiniz. Pekala, işte organize edilmeden nedenlerin bir listesi: +Using getters and setters to access data on objects could be better than simply +looking for a property on an object. "Why?" you might ask. Well, here's an +unorganized list of reasons why: -- Bir nesne özelliği almanın ötesinde daha fazlasını yapmak istediğinizde, kod tabanınızdaki her erişimciye bakmanız ve değiştirmeniz gerekmez. -- `set`yaparken doğrulama basitçe yapılabilir. -- Dahili gösterimi içine alır. -- Alma ve ayarlama sırasında kayıtlamayı(logging) ve hata yönetimi(error handling) eklemek kolaydır. -- Diyelimki sunucudan alıyorsunuz, nesnenizin özelliklerini tembel(lazy load) olarak yükleyebilirsiniz. +- When you want to do more beyond getting an object property, you don't have + to look up and change every accessor in your codebase. +- Makes adding validation simple when doing a `set`. +- Encapsulates the internal representation. +- Easy to add logging and error handling when getting and setting. +- You can lazy load your object's properties, let's say getting it from a + server. -**Kötü:** +**Bad:** ```javascript function makeBankAccount() { @@ -954,19 +1065,19 @@ const account = makeBankAccount(); account.balance = 100; ``` -**İyi:** +**Good:** ```javascript function makeBankAccount() { - // Bu fonksiyon özelinde (private) + // this one is private let balance = 0; - // "alıcı"yı, genel(public) objeyi döndürerek yap + // a "getter", made public via the returned object below function getBalance() { return balance; } - - // "ayarlayıcı"yı, genel(public) objeyi döndürerek yap + + // a "setter", made public via the returned object below function setBalance(amount) { // ... validate before updating the balance balance = amount; @@ -983,13 +1094,13 @@ const account = makeBankAccount(); account.setBalance(100); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Nesnelerin özel üyeleri olmasını sağlama +### Make objects have private members This can be accomplished through closures (for ES5 and below). -**Kötü:** +**Bad:** ```javascript const Employee = function(name) { @@ -1006,7 +1117,7 @@ delete employee.name; console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined ``` -**İyi:** +**Good:** ```javascript function makeEmployee(name) { @@ -1023,15 +1134,18 @@ delete employee.name; console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Sınıflar** +## **Classes** -### ES5 düz fonksiyonlar yerine ES2015 / ES6 sınıflarını tercih et +### Prefer ES2015/ES6 classes over ES5 plain functions -Klasik ES5 sınıfları için okunabilir sınıf mirası, yapısı ve yöntem tanımları almak çok zordur. Miras almaya(inheritance) ihtiyacınız varsa (ve gerekmeyebileceğini unutmayın), ES2015 / ES6 sınıflarını tercih edin. Bununla birlikte, kendinizi daha büyük ve daha karmaşık nesnelere ihtiyaç duyana kadar küçük işlevlere tercih edin. +It's very difficult to get readable class inheritance, construction, and method +definitions for classical ES5 classes. If you need inheritance (and be aware +that you might not), then prefer ES2015/ES6 classes. However, prefer small functions over +classes until you find yourself needing larger and more complex objects. -**Kötü:** +**Bad:** ```javascript const Animal = function(age) { @@ -1071,7 +1185,7 @@ Human.prototype.constructor = Human; Human.prototype.speak = function speak() {}; ``` -**İyi:** +**Good:** ```javascript class Animal { @@ -1107,13 +1221,17 @@ class Human extends Mammal { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yöntem zincirini kullan +### Use method chaining -Bu desen JavaScript'te çok kullanışlıdır ve jQuery ve Lodash gibi birçok kütüphanede görürsünüz. Kodunuzun etkileyici ve daha az detaylı olmasını sağlar. Bu nedenle, diyorum ki, yöntem zincirleme kullanın ve kodunuzun ne kadar temiz olacağını göreceksiniz. Sınıf fonksiyonlarınızda, her fonksiyonun sonunda `this`'i döndürmeniz yeterlidir ve daha fazla sınıf yöntemini buna zincirleyebilirsiniz. +This pattern is very useful in JavaScript and you see it in many libraries such +as jQuery and Lodash. It allows your code to be expressive, and less verbose. +For that reason, I say, use method chaining and take a look at how clean your code +will be. In your class functions, simply return `this` at the end of every function, +and you can chain further class methods onto it. -**Kötü:** +**Bad:** ```javascript class Car { @@ -1145,7 +1263,7 @@ car.setColor("pink"); car.save(); ``` -**İyi:** +**Good:** ```javascript class Car { @@ -1157,25 +1275,25 @@ class Car { setMake(make) { this.make = make; - // NOT: Zincirleme için `this` döndür + // NOTE: Returning this for chaining return this; } setModel(model) { this.model = model; - // NOT: Zincirleme için `this` döndür + // NOTE: Returning this for chaining return this; } setColor(color) { this.color = color; - // NOT: Zincirleme için `this` döndür + // NOTE: Returning this for chaining return this; } save() { console.log(this.make, this.model, this.color); - // NOT: Zincirleme için `this` döndür + // NOTE: Returning this for chaining return this; } } @@ -1183,19 +1301,28 @@ class Car { const car = new Car("Ford", "F-150", "red").setColor("pink").save(); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Miras yerine kompozisyon tercih et +### Prefer composition over inheritance -Dörtlü çete tarafından başlatılan ünlü [_Tasarım Desenleri_](https://en.wikipedia.org/wiki/Design_Patterns) gibi, siz de kompozisyonu, miras bırakmaya yerine göre tercih etmelisiniz. Miras kullanmak için birçok iyi neden ve kompozisyon kullanmak için birçok iyi neden vardır. Bu maksimum nokta için ana nokta, zihniniz içgüdüsel olarak miras kullanma için giderse, kompozisyon sorununuzu daha iyi modelleyip değiştiremeyeceğini düşünmeye çalışın. Bazı durumlarda olabilir. +As stated famously in [_Design Patterns_](https://en.wikipedia.org/wiki/Design_Patterns) by the Gang of Four, +you should prefer composition over inheritance where you can. There are lots of +good reasons to use inheritance and lots of good reasons to use composition. +The main point for this maxim is that if your mind instinctively goes for +inheritance, try to think if composition could model your problem better. In some +cases it can. -O zaman "ne zaman miras kullanmalıyım?" diye merak ediyor olabilirsiniz. O eldeki probleminize bağlıdır, ancak bu mirasın kompozisyondan daha mantıklı olduğu iyi bir listedir: +You might be wondering then, "when should I use inheritance?" It +depends on your problem at hand, but this is a decent list of when inheritance +makes more sense than composition: -1. Mirasınız "has-a" değil, "is-a" ilişkisini temsil eder ilişki (İnsan-> Hayvan ve Kullanıcı-> KullanıcıAyrıntıları). -2. Temel sınıflardan kodu yeniden kullanabilirsiniz (İnsanlar tüm hayvanlar gibi hareket edebilir). -3. Temel sınıfı değiştirerek türetilmiş sınıflarda genel değişiklikler yapmak istiyorsunuz. (Hareket ettiklerinde tüm hayvanların kalori harcamalarını değiştirin). +1. Your inheritance represents an "is-a" relationship and not a "has-a" + relationship (Human->Animal vs. User->UserDetails). +2. You can reuse code from the base classes (Humans can move like all animals). +3. You want to make global changes to derived classes by changing a base class. + (Change the caloric expenditure of all animals when they move). -**Kötü:** +**Bad:** ```javascript class Employee { @@ -1207,7 +1334,7 @@ class Employee { // ... } -// Kötü çünkü Çalışanların(Employees) vergi bilgisi 'var'. ÇalışanVergiBilgisi(EmployeeTaxData) bir çeşit Çalışan(Employee) değil. +// Bad because Employees "have" tax data. EmployeeTaxData is not a type of Employee class EmployeeTaxData extends Employee { constructor(ssn, salary) { super(); @@ -1219,7 +1346,7 @@ class EmployeeTaxData extends Employee { } ``` -**İyi:** +**Good:** ```javascript class EmployeeTaxData { @@ -1244,15 +1371,22 @@ class Employee { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** ## **SOLID** -### Tek Sorumluluk İlkesi (SRP) +### Single Responsibility Principle (SRP) -Temiz Kod'da belirtildiği gibi, "Bir sınıfın değişmesi için asla birden fazla sebep olmamalıdır". Bir sınıfı tıklım tıklım bir çok işlevsellikle doldurmak çekici gelebilir, tıpkı uçuşlarda yanına alabileceğiniz bir valiz gibi. Bununla ilgili sorun, sınıfınızın kavramsal olarak uyumlu olmayacağı ve değişmesi için birçok neden vereceği yönündedir. Bir sınıfı değiştirmek için ihtiyaç duyduğunuz sayıyı en aza indirmek önemlidir. Bir sınıfta çok fazla işlevsellik varsa ve bir parçasını değiştirirseniz, bunun kod tabanınızdaki diğer bağımlı modülleri nasıl etkileyeceğini anlamak zor olabilir. +As stated in Clean Code, "There should never be more than one reason for a class +to change". It's tempting to jam-pack a class with a lot of functionality, like +when you can only take one suitcase on your flight. The issue with this is +that your class won't be conceptually cohesive and it will give it many reasons +to change. Minimizing the amount of times you need to change a class is important. +It's important because if too much functionality is in one class and you modify +a piece of it, it can be difficult to understand how that will affect other +dependent modules in your codebase. -**Kötü:** +**Bad:** ```javascript class UserSettings { @@ -1272,7 +1406,7 @@ class UserSettings { } ``` -**İyi:** +**Good:** ```javascript class UserAuth { @@ -1299,13 +1433,16 @@ class UserSettings { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Açık / Kapalı Prensibi (OCP) +### Open/Closed Principle (OCP) -Bertrand Meyer tarafından belirtildiği gibi, "yazılım varlıkları (sınıflar, modüller, işlevler, vb.) Genişletme için açık, ancak değişiklik için kapalı olmalıdır." Bu ne anlama geliyor? Bu ilke, temel olarak kullanıcıların mevcut kodu değiştirmeden yeni işlevler eklemelerine izin vermeniz gerektiğini belirtir. +As stated by Bertrand Meyer, "software entities (classes, modules, functions, +etc.) should be open for extension, but closed for modification." What does that +mean though? This principle basically states that you should allow users to +add new functionalities without changing existing code. -**Kötü:** +**Bad:** ```javascript class AjaxAdapter extends Adapter { @@ -1349,7 +1486,7 @@ function makeHttpCall(url) { } ``` -**İyi:** +**Good:** ```javascript class AjaxAdapter extends Adapter { @@ -1387,15 +1524,24 @@ class HttpRequester { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Liskov’un Yerine Geçme Prensibi (LSP) +### Liskov Substitution Principle (LSP) -Bu çok basit bir kavram için korkutucu bir terimdir.Resmi olarak "S, T'nin bir alt tipiyse, o zaman T tipi nesnelerin yerine S tipi nesneler (yani, S tipi nesneler T programındaki nesnelerin yerine geçebilir), bu programın istenen özelliklerini değiştirmeden değiştirilebilir (doğruluk, yapılan görev vb.) " Bu daha da korkunç bir tanım. +This is a scary term for a very simple concept. It's formally defined as "If S +is a subtype of T, then objects of type T may be replaced with objects of type S +(i.e., objects of type S may substitute objects of type T) without altering any +of the desirable properties of that program (correctness, task performed, +etc.)." That's an even scarier definition. -Bunun için en iyi açıklama, bir üst sınıfınız ve bir alt sınıfınız varsa, temel sınıf ve alt sınıf yanlış sonuçlar elde etmeden birbirinin yerine kullanılabilir.Bu hala kafa karıştırıcı olabilir, bu yüzden klasik Kare Dikdörtgen örneğine bakalım. Matematiksel olarak, bir kare bir dikdörtgendir, ancak miras yoluyla "is-a" ilişkisini kullanarak model verirseniz, hızlı bir şekilde sorun yaşarsınız. +The best explanation for this is if you have a parent class and a child class, +then the base class and child class can be used interchangeably without getting +incorrect results. This might still be confusing, so let's take a look at the +classic Square-Rectangle example. Mathematically, a square is a rectangle, but +if you model it using the "is-a" relationship via inheritance, you quickly +get into trouble. -**Kötü:** +**Bad:** ```javascript class Rectangle { @@ -1441,7 +1587,7 @@ function renderLargeRectangles(rectangles) { rectangles.forEach(rectangle => { rectangle.setWidth(4); rectangle.setHeight(5); - const area = rectangle.getArea(); // KÖTÜ: Kare için 25 değerini döndürür. 20 olmalı. + const area = rectangle.getArea(); // BAD: Returns 25 for Square. Should be 20. rectangle.render(area); }); } @@ -1450,7 +1596,7 @@ const rectangles = [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles(rectangles); ``` -**İyi:** +**Good:** ```javascript class Shape { @@ -1497,17 +1643,25 @@ const shapes = [new Rectangle(4, 5), new Rectangle(4, 5), new Square(5)]; renderLargeShapes(shapes); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Arayüzlerin Ayrımı Prensibi (ISP) +### Interface Segregation Principle (ISP) -JavaScript'in arayüzleri yoktur, bu nedenle bu ilke diğerleri kadar kesin olarak geçerli değildir. Bununla birlikte, JavaScript'in tür sistemi eksikliğinde bile önemli ve alâkalıdır. +JavaScript doesn't have interfaces so this principle doesn't apply as strictly +as others. However, it's important and relevant even with JavaScript's lack of +type system. -ISP, "kullanıcılar kullanmadığı arabirimlere bağımlı olmaya zorlanmamalıdır." der. Arabirimler, `Duck Typing` yüzünden JavaScript'de üstü kapalı anlaşmalardır. +ISP states that "Clients should not be forced to depend upon interfaces that +they do not use." Interfaces are implicit contracts in JavaScript because of +duck typing. -Bu ilkeyi JavaScript'te gösteren iyi bir örnek, sınıflar büyük ayar nesneleri gerektirir. Kullanıcıların büyük miktarda seçenek ayarlamalarını istememek gerekli değildir, çünkü çoğu zaman tüm ayarlara ihtiyaç duymazlar. Bunları isteğe bağlı yapmak, bir "büyük arayüzü" olmasını önlemeye yardımcı olur. +A good example to look at that demonstrates this principle in JavaScript is for +classes that require large settings objects. Not requiring clients to setup +huge amounts of options is beneficial, because most of the time they won't need +all of the settings. Making them optional helps prevent having a +"fat interface". -**Kötü:** +**Bad:** ```javascript class DOMTraverser { @@ -1528,12 +1682,12 @@ class DOMTraverser { const $ = new DOMTraverser({ rootNode: document.getElementsByTagName("body"), - animationModule() {} // Coğunlukla, bunu canlandırmamız gerekmeyecek + animationModule() {} // Most of the time, we won't need to animate when traversing. // ... }); ``` -**İyi:** +**Good:** ```javascript class DOMTraverser { @@ -1567,24 +1721,32 @@ const $ = new DOMTraverser({ }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Bağlılığı Tersine Çevirme Prensibi (DIP) +### Dependency Inversion Principle (DIP) -Bu ilke iki temel şeyi ifade eder: +This principle states two essential things: -1. Yüksek seviyeli modüller, düşük seviyeli modüllere bağlı olmamalıdır. Her ikisi de soyutlamalara bağlı olmalıdır. -2. Soyutlamalar detaylara bağlı olmamalıdır. Ayrıntılar soyutlamalara bağlı olmalıdır. +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. -İlk başta bunu anlamak zor olabilir, ancak AngularJS ile çalıştıysanız, bu prensibin Bağımlılık Enjeksiyonu (DI) şeklinde bir uygulamasını gördünüz. Aynı kavramlar olmasalar da, DIP yüksek seviyede modüllerin düşük seviyeli modüllerinin detaylarını bilmelerini ve ayarlamalarını sağlar. -Bunu DI ile başarabilir. Bunun büyük bir yararı, modüller arasındaki bağlantıyı azaltmasıdır. Eşleştirme(Coupling) çok kötü bir gelişme modelidir çünkü -kodunuzu yeniden düzenleme zorlaştırır. +This can be hard to understand at first, but if you've worked with AngularJS, +you've seen an implementation of this principle in the form of Dependency +Injection (DI). While they are not identical concepts, DIP keeps high-level +modules from knowing the details of its low-level modules and setting them up. +It can accomplish this through DI. A huge benefit of this is that it reduces +the coupling between modules. Coupling is a very bad development pattern because +it makes your code hard to refactor. -Daha önce belirtildiği gibi, JavaScript'in arayüzleri yoktur, bu nedenle soyutlamalar örtük sözleşmelere bağlıdır. -Yani, bir nesnenin / sınıfın başka bir nesneye / sınıfa maruz bıraktığı yöntemler ve özellikler. -Aşağıdaki örnekte, örtük sözleşme, bir `InventoryTracker` için herhangi bir Request modülünün `requestItems` yöntemine sahip olacağıdır. +As stated previously, JavaScript doesn't have interfaces so the abstractions +that are depended upon are implicit contracts. That is to say, the methods +and properties that an object/class exposes to another object/class. In the +example below, the implicit contract is that any Request module for an +`InventoryTracker` will have a `requestItems` method. -**Kötü:** +**Bad:** ```javascript class InventoryRequester { @@ -1601,8 +1763,8 @@ class InventoryTracker { constructor(items) { this.items = items; - // KÖTÜ: Belirli bir istek uygulamasına bağımlılık yarattık. -    // requestItems sadece `request` 'e bağlımlı olmalıdır. + // BAD: We have created a dependency on a specific request implementation. + // We should just have requestItems depend on a request method: `request` this.requester = new InventoryRequester(); } @@ -1617,7 +1779,7 @@ const inventoryTracker = new InventoryTracker(["apples", "bananas"]); inventoryTracker.requestItems(); ``` -**İyi:** +**Good:** ```javascript class InventoryTracker { @@ -1653,8 +1815,8 @@ class InventoryRequesterV2 { } } -// Bağımlılıklarımızı harici olarak yapılandırarak ve enjekte ederek -// istek modülümüzü WebSockets kullanan yeni ve havalı bir modülle kolayca değiştirebiliriz. +// By constructing our dependencies externally and injecting them, we can easily +// substitute our request module for a fancy new one that uses WebSockets. const inventoryTracker = new InventoryTracker( ["apples", "bananas"], new InventoryRequesterV2() @@ -1662,19 +1824,28 @@ const inventoryTracker = new InventoryTracker( inventoryTracker.requestItems(); ``` -**[⬆ Başa dön](#İçindekiler)** - -## **Testler** +**[⬆ back to top](#table-of-contents)** -Test etmek canlıya çıkmaktan bile önemlidir. Eğer testiniz yoksa veya yetersiz bir miktardaysa, kodu her gönderdiğinizde hiçbir şeyin bozulmadığına emin olmazsınız. Neyin yeterli bir miktar oluşturduğuna karar vermek takımınıza bağlıdır, %100 kapsama sahip olmak (tüm ifadeler ve şubeler) size güven ve gönül rahatlığı sağlar. Bu, harika bir test framework'üne sahip olmanın yanı sıra, [iyi bir kapsama aracı](https://gotwarlost.github.io/istanbul/) kullanmanız gerektiği anlamına gelir +## **Testing** -Test yazmamanın mazereti yoktur. Çok sayıda [iyi JS test framework'ü](https://jstherightway.org/#testing-tools) vardır, bu yüzden ekibinize uyan birini bulun. +Testing is more important than shipping. If you have no tests or an +inadequate amount, then every time you ship code you won't be sure that you +didn't break anything. Deciding on what constitutes an adequate amount is up +to your team, but having 100% coverage (all statements and branches) is how +you achieve very high confidence and developer peace of mind. This means that +in addition to having a great testing framework, you also need to use a +[good coverage tool](https://gotwarlost.github.io/istanbul/). -Ekibiniz için uygun olanı bulduğunuzda, kullanılan her yeni özellik / modül için daima testler yazmayı hedefleyin. Tercih ettiğiniz yöntem Test Odaklı Geliştirme (TDD) ise, bu harika, ancak asıl mesele, herhangi bir özelliği başlatmadan veya mevcut bir özelliği yeniden düzenlemeden önce kapsama hedeflerinize ulaştığınızdan emin olmaktır. +There's no excuse to not write tests. There are [plenty of good JS test frameworks](https://jstherightway.org/#testing-tools), so find one that your team prefers. +When you find one that works for your team, then aim to always write tests +for every new feature/module you introduce. If your preferred method is +Test Driven Development (TDD), that is great, but the main point is to just +make sure you are reaching your coverage goals before launching any feature, +or refactoring an existing one. -### Her test için tek konsept +### Single concept per test -**Kötü:** +**Bad:** ```javascript import assert from "assert"; @@ -1698,7 +1869,7 @@ describe("MomentJS", () => { }); ``` -**İyi:** +**Good:** ```javascript import assert from "assert"; @@ -1724,15 +1895,16 @@ describe("MomentJS", () => { }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Tutarlılık** +## **Concurrency** -### Promises kullanın, callback değil +### Use Promises, not callbacks -'Callback'ler temiz değildir ve aşırı miktarda iç içe geçmeye neden olurlar. ES2015 / ES6 ile Promise'ler yerleşik bir global tiptir. Onları kullan! +Callbacks aren't clean, and they cause excessive amounts of nesting. With ES2015/ES6, +Promises are a built-in global type. Use them! -**Kötü:** +**Bad:** ```javascript import { get } from "request"; @@ -1756,7 +1928,7 @@ get( ); ``` -**İyi:** +**Good:** ```javascript import { get } from "request-promise"; @@ -1774,13 +1946,17 @@ get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Async/Await kullanmak Promis kullanmaktan bile daha temiz +### Async/Await are even cleaner than Promises -Promise'ler callback'lere göte çok daha temiz alternatiflerdir, ama ES2017/ES8 async ve await getirdi ve bu daha temiz bir çözüm sunuyor. Tek yapmanız gereken fonksiyonun başına `async` eklemek ve sonrasında mantıksal kullanımızı `then` zinciri kulanmadan yazabilirsiniz. Bugün ES2017 / ES8 özelliklerinden yararlanabiliyorsanız bunu kullanın! +Promises are a very clean alternative to callbacks, but ES2017/ES8 brings async and await +which offer an even cleaner solution. All you need is a function that is prefixed +in an `async` keyword, and then you can write your logic imperatively without +a `then` chain of functions. Use this if you can take advantage of ES2017/ES8 features +today! -**Kötü:** +**Bad:** ```javascript import { get } from "request-promise"; @@ -1798,7 +1974,7 @@ get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin") }); ``` -**İyi:** +**Good:** ```javascript import { get } from "request-promise"; @@ -1819,21 +1995,25 @@ async function getCleanCodeArticle() { getCleanCodeArticle() ``` -**[⬆ Başa dön](#İçindekiler)** - -## **Hata Yönetimi** - -Atılan hatalar iyi bir şey! Bunlar, programınızdaki bir şey yanlış gittiğinde çalışma zamanının başarıyla tanımlandığı anlamına gelir ve sizi geçerli yığında (stack) fonksiyonu çalıştırmayı, işlevi dururup size konsolda yığın izlemede haber vererek yapar. +**[⬆ back to top](#table-of-contents)** ---- HERE +## **Error Handling** -### Yakalanmış hataları görmemezlikten gelmeyin +Thrown errors are a good thing! They mean the runtime has successfully +identified when something in your program has gone wrong and it's letting +you know by stopping function execution on the current stack, killing the +process (in Node), and notifying you in the console with a stack trace. -Yakalanan bir hatayla hiçbir şey yapmamanız size söz konusu hatayı düzeltebilme veya tepki gösterme yeteneği vermez. Hatayı konsola (`console.log`) kaydetmek, konsola yazdırılan bir şey denizinde kaybolabileceği sıklıkta daha iyi değildir. +### Don't ignore caught errors -Herhangi bir kod parçasını `try/catch` içerisinde kullanıyorsanız, orada bir hata olabileceğini düşündüğünüz anlamına gelir ve bu nedenle gerçekleştiği zaman için bir planınız olması veya bir kod yolu oluşturmanız gerekir. +Doing nothing with a caught error doesn't give you the ability to ever fix +or react to said error. Logging the error to the console (`console.log`) +isn't much better as often times it can get lost in a sea of things printed +to the console. If you wrap any bit of code in a `try/catch` it means you +think an error may occur there and therefore you should have a plan, +or create a code path, for when it occurs. -**Kötü:** +**Bad:** ```javascript try { @@ -1843,27 +2023,28 @@ try { } ``` -**İyi:** +**Good:** ```javascript try { functionThatMightThrow(); } catch (error) { - // Bir secenek (console.log'dan daha dikkat çekici) + // One option (more noisy than console.log): console.error(error); - // Bir secenek daha + // Another option: notifyUserOfError(error); - // Bir secenek daha + // Another option: reportErrorToService(error); - // veya hepsini bir yapın + // OR do all three! } ``` -### Reddedilmiş promisleri görmemezlikten gelmeyin +### Don't ignore rejected promises -Aynı sebeplerden dolayı, `try/catch`'de oluşan hataları yok saymamalısınız +For the same reason you shouldn't ignore caught errors +from `try/catch`. -**Kötü:** +**Bad:** ```javascript getdata() @@ -1875,7 +2056,7 @@ getdata() }); ``` -**İyi:** +**Good:** ```javascript getdata() @@ -1883,29 +2064,36 @@ getdata() functionThatMightThrow(data); }) .catch(error => { - // Bir secenek (console.log'dan daha dikkat çekici) + // One option (more noisy than console.log): console.error(error); - // Bir secenek daha + // Another option: notifyUserOfError(error); - // Bir secenek daha + // Another option: reportErrorToService(error); - // veya hepsini bir yapın + // OR do all three! }); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Biçimlendirme** +## **Formatting** -Biçimlendirme özneldir. Buradaki birçok kural gibi, uygulamanız gereken zor ve hızlı bir kural yoktur. Ana nokta biçimlendirme üzerinde tartışma DEĞİLDİR. Bunu otomatikleştirmek için [tonlarca araç](https://standardjs.com/rules.html) vardır. Birini kullan! Mühendislerin biçimlendirme konusunda tartışmaları zaman ve para kaybıdır. +Formatting is subjective. Like many rules herein, there is no hard and fast +rule that you must follow. The main point is DO NOT ARGUE over formatting. +There are [tons of tools](https://standardjs.com/rules.html) to automate this. +Use one! It's a waste of time and money for engineers to argue over formatting. -Otomatik biçimlendirme (girintileme, sekmeler ve boşluklar, çift veya tek tırnak işaretleri vb.) Kapsamına girmeyen şeyler için bazı rehberlik için buraya bakın. +For things that don't fall under the purview of automatic formatting +(indentation, tabs vs. spaces, double vs. single quotes, etc.) look here +for some guidance. -### Tutarlı büyük harf kullanımı +### Use consistent capitalization -JavaScript türsüzdür, bu nedenle büyük / küçük harf kullanımı değişkenleriniz, işlevleriniz vb. Hakkında çok şey anlatır. Bu kurallar özneldir, böylece ekibiniz istediklerini seçebilir. Mesele şu ki, ne seçerseniz seçin, tutarlı olun. +JavaScript is untyped, so capitalization tells you a lot about your variables, +functions, etc. These rules are subjective, so your team can choose whatever +they want. The point is, no matter what you all choose, just be consistent. -**Kötü:** +**Bad:** ```javascript const DAYS_IN_WEEK = 7; @@ -1921,7 +2109,7 @@ class animal {} class Alpaca {} ``` -**İyi:** +**Good:** ```javascript const DAYS_IN_WEEK = 7; @@ -1937,13 +2125,15 @@ class Animal {} class Alpaca {} ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Fonksion çağıranları ve çağrılanları yakın olmalı +### Function callers and callees should be close -Eğer bir fonksiyon diğer fonksiyonu çağırıyorsa, dikey olarak bu fonksiyonları kaynak dosyasında yakın tutun. İdeal olan, fonksiyonu kullanan kullandığı fonksiyonun hemen üstünde olmasıdır. We tend to read code from top-to-bottom, like a newspaper.Bu nedenle, kodunuzu bu şekilde okuyun. +If a function calls another, keep those functions vertically close in the source +file. Ideally, keep the caller right above the callee. We tend to read code from +top-to-bottom, like a newspaper. Because of this, make your code read that way. -**Kötü:** +**Bad:** ```javascript class PerformanceReview { @@ -1983,7 +2173,7 @@ const review = new PerformanceReview(employee); review.perfReview(); ``` -**İyi:** +**Good:** ```javascript class PerformanceReview { @@ -2023,37 +2213,37 @@ const review = new PerformanceReview(employee); review.perfReview(); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## **Yorumlar** +## **Comments** -### Yalnızca iş mantığı karmaşıklığı olan şeyleri yorumlayın +### Only comment things that have business logic complexity. -Yorumlar aslında bir özür, şart değil. İyi kod _çoğunlukla_ kendini belgelemektedir. +Comments are an apology, not a requirement. Good code _mostly_ documents itself. -**Kötü:** +**Bad:** ```javascript function hashIt(data) { - // Karma + // The hash let hash = 0; - // String uzunluğu + // Length of string const length = data.length; - // Verilerdeki her karakteri gözden geçirin + // Loop through every character in data for (let i = 0; i < length; i++) { - // Karakter kodunu al + // Get character code. const char = data.charCodeAt(i); - // Karıştır + // Make the hash hash = (hash << 5) - hash + char; - // 32-bit tam sayıya dönüştür + // Convert to 32-bit integer hash &= hash; } } ``` -**İyi:** +**Good:** ```javascript function hashIt(data) { @@ -2064,19 +2254,19 @@ function hashIt(data) { const char = data.charCodeAt(i); hash = (hash << 5) - hash + char; - // 32-bit tam sayıya dönüştür + // Convert to 32-bit integer hash &= hash; } } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Kodlarınızı yorum olarak bırakmayın +### Don't leave commented out code in your codebase -Versiyon kontrol'un var olmasının bir sebebi var. Eski kodlarınızı tarihin tozlu sayfalarında bırakın. +Version control exists for a reason. Leave old code in your history. -**Kötü:** +**Bad:** ```javascript doStuff(); @@ -2085,19 +2275,20 @@ doStuff(); // doSoMuchStuff(); ``` -**İyi:** +**Good:** ```javascript doStuff(); ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Günlük yorumları yapmayın +### Don't have journal comments -Hatırlayın, versiyon kontrol kullanın! Kullanılmayan koda, yoruma alınmış koda ve özellikle günlük kodlarına gerek yok. Geçmiş için `git log` kullanın. +Remember, use version control! There's no need for dead code, commented code, +and especially journal comments. Use `git log` to get history! -**Kötü:** +**Bad:** ```javascript /** @@ -2111,7 +2302,7 @@ function combine(a, b) { } ``` -**İyi:** +**Good:** ```javascript function combine(a, b) { @@ -2119,13 +2310,14 @@ function combine(a, b) { } ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -### Yer belirleyicilerden kaçının +### Avoid positional markers -Bunlar genellikle kirlilik yaratır. Fonksiyonların ve değişken adlarının yanı sıra uygun girinti ve biçimlendirme kodunuza görsel yapı kazandırsın. +They usually just add noise. Let the functions and variable names along with the +proper indentation and formatting give the visual structure to your code. -**Kötü:** +**Bad:** ```javascript //////////////////////////////////////////////////////////////////////////////// @@ -2144,7 +2336,7 @@ const actions = function() { }; ``` -**İyi:** +**Good:** ```javascript $scope.model = { @@ -2157,11 +2349,11 @@ const actions = function() { }; ``` -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** -## Çeviriler +## Translation -Ayrıca diğer dillerde de: +This is also available in other languages: - ![am](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Armenia.png) **Armenian**: [hanumanum/clean-code-javascript/](https://github.com/hanumanum/clean-code-javascript) - ![bd](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Bangladesh.png) **Bangla(বাংলা)**: [InsomniacSabbir/clean-code-javascript/](https://github.com/InsomniacSabbir/clean-code-javascript/) @@ -2182,7 +2374,7 @@ Ayrıca diğer dillerde de: - [maksugr/clean-code-javascript](https://github.com/maksugr/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [tureey/clean-code-javascript](https://github.com/tureey/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Uruguay.png) **Spanish**: [andersontr15/clean-code-javascript](https://github.com/andersontr15/clean-code-javascript-es) -- ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript) +- ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript/tree/turkish-translation) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) -**[⬆ Başa dön](#İçindekiler)** +**[⬆ back to top](#table-of-contents)** From ec7baf25c13147d62d175d9518d24aa2fff56cc1 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 1 Apr 2020 18:47:12 +0300 Subject: [PATCH 14/24] Fix calling animationModule in ISP bad example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bfe4c85..61890f35 100644 --- a/README.md +++ b/README.md @@ -1672,7 +1672,7 @@ class DOMTraverser { setup() { this.rootNode = this.settings.rootNode; - this.animationModule.setup(); + this.settings.animationModule.setup(); } traverse() { From 93888080dd76f609ff36a233cc40d53593208805 Mon Sep 17 00:00:00 2001 From: Oleksandr Zaychenko Date: Thu, 16 Apr 2020 16:57:44 +0300 Subject: [PATCH 15/24] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0bfe4c85..2bbc443e 100644 --- a/README.md +++ b/README.md @@ -2375,6 +2375,7 @@ This is also available in other languages: - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [tureey/clean-code-javascript](https://github.com/tureey/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Uruguay.png) **Spanish**: [andersontr15/clean-code-javascript](https://github.com/andersontr15/clean-code-javascript-es) - ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript/tree/turkish-translation) +- ![ua](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Ukraine.png) **Ukrainian**: [mindfr1k/clean-code-javascript-ua](https://github.com/mindfr1k/clean-code-javascript-ua) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) **[⬆ back to top](#table-of-contents)** From 365717f8bb54f0046e226606b0bbd3c9123e3594 Mon Sep 17 00:00:00 2001 From: Yaniv Chekroun Date: Sun, 6 Sep 2020 15:23:12 +0300 Subject: [PATCH 16/24] Add calculation for milliseconds in a day --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23ffbd33..fbe4de71 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ setTimeout(blastOff, 86400000); ```javascript // Declare them as capitalized named constants. -const MILLISECONDS_IN_A_DAY = 86_400_000; +const MILLISECONDS_IN_A_DAY = 60 * 60 * 24 * 1000; //86400000; setTimeout(blastOff, MILLISECONDS_IN_A_DAY); ``` From 3b9504ef2ac585fadeec0523bb22ca39ca626e6b Mon Sep 17 00:00:00 2001 From: "J.D. Sandifer" Date: Sun, 4 Oct 2020 20:50:25 -0700 Subject: [PATCH 17/24] Replace pass-by-reference with mutability, clean up This edit only affects the Avoid Side Effects (part 2) section. It replaces the discussion of pass by reference with an explanation in terms of mutability. By avoiding the confusing terminology and possible links to the implementation details of different JS engines the explanation can be kept at an abstraction level that's great for beginners and experts alike. I also cleaned up some grammar, typos, etc. --- README.md | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 23ffbd33..a67a044b 100644 --- a/README.md +++ b/README.md @@ -643,26 +643,29 @@ console.log(newName); // ['Ryan', 'McDermott']; ### Avoid Side Effects (part 2) -In JavaScript, primitives are passed by value and objects/arrays are passed by -reference. In the case of objects and arrays, if your function makes a change -in a shopping cart array, for example, by adding an item to purchase, -then any other function that uses that `cart` array will be affected by this -addition. That may be great, however it can be bad too. Let's imagine a bad -situation: +In JavaScript, some values are unchangeable (immutable) and some are changeable +(mutable). Objects and arrays are two kinds of mutable values so it's important +to handle them carefully when they're passed as parameters to a function. A +JavaScript function can change an object's properties or alter the contents of +an array which could easily cause bugs elsewhere. + +Suppose there's a function that accepts an array parameter representing a +shopping cart. If the function makes a change in that shopping cart array +- by adding an item to purchase, for example - then any other function that +uses that same `cart` array will be affected by this addition. That may be +great, however it could also be bad. Let's imagine a bad situation: The user clicks the "Purchase" button which calls a `purchase` function that spawns a network request and sends the `cart` array to the server. Because of a bad network connection, the `purchase` function has to keep retrying the -request. Now, what if in the meantime the user accidentally clicks "Add to Cart" +request. Now, what if in the meantime the user accidentally clicks an "Add to Cart" button on an item they don't actually want before the network request begins? If that happens and the network request begins, then that purchase function -will send the accidentally added item because it has a reference to a shopping -cart array that the `addItemToCart` function modified by adding an unwanted -item. +will send the accidentally added item because the `cart` array was modified. -A great solution would be for the `addItemToCart` to always clone the `cart`, -edit it, and return the clone. This ensures that no other functions that are -holding onto a reference of the shopping cart will be affected by any changes. +A great solution would be for the `addItemToCart` function to always clone the +`cart`, edit it, and return the clone. This would ensure that functions that are still +using the old shopping cart wouldn't be affected by the changes. Two caveats to mention to this approach: From 30282195952b7eb01d2c8e0f022f83d60cde9284 Mon Sep 17 00:00:00 2001 From: "J.D. Sandifer" Date: Wed, 7 Oct 2020 20:15:53 -0700 Subject: [PATCH 18/24] Fix stray hyphen turning into a random bullet --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a67a044b..e5b63a81 100644 --- a/README.md +++ b/README.md @@ -650,8 +650,8 @@ JavaScript function can change an object's properties or alter the contents of an array which could easily cause bugs elsewhere. Suppose there's a function that accepts an array parameter representing a -shopping cart. If the function makes a change in that shopping cart array -- by adding an item to purchase, for example - then any other function that +shopping cart. If the function makes a change in that shopping cart array - +by adding an item to purchase, for example - then any other function that uses that same `cart` array will be affected by this addition. That may be great, however it could also be bad. Let's imagine a bad situation: From 029c4c2f8aef211caa99ab4cd39dcdbd496ba669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Doskovi=C4=87?= <40147841+doskovicmilos@users.noreply.github.com> Date: Sat, 10 Oct 2020 18:04:42 +0200 Subject: [PATCH 19/24] Add Serbian translation. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6205f631..ad21e9aa 100644 --- a/README.md +++ b/README.md @@ -2377,6 +2377,7 @@ This is also available in other languages: - [maksugr/clean-code-javascript](https://github.com/maksugr/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Spain.png) **Spanish**: [tureey/clean-code-javascript](https://github.com/tureey/clean-code-javascript) - ![es](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Uruguay.png) **Spanish**: [andersontr15/clean-code-javascript](https://github.com/andersontr15/clean-code-javascript-es) +- ![rs](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Serbia.png) **Serbian**: [doskovicmilos/clean-code-javascript/](https://github.com/doskovicmilos/clean-code-javascript) - ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript/tree/turkish-translation) - ![ua](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Ukraine.png) **Ukrainian**: [mindfr1k/clean-code-javascript-ua](https://github.com/mindfr1k/clean-code-javascript-ua) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) From 753d6d8b33dece69e08b2ec0ea0807592881fbf2 Mon Sep 17 00:00:00 2001 From: James Tharpe Date: Mon, 29 Mar 2021 08:38:27 -0400 Subject: [PATCH 20/24] Make example more succinct "PER" has the same meaning as "IN_A" but is less verbose --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ad21e9aa..71896ed4 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,9 @@ setTimeout(blastOff, 86400000); ```javascript // Declare them as capitalized named constants. -const MILLISECONDS_IN_A_DAY = 60 * 60 * 24 * 1000; //86400000; +const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000; //86400000; -setTimeout(blastOff, MILLISECONDS_IN_A_DAY); +setTimeout(blastOff, MILLISECONDS_PER_DAY); ``` **[⬆ back to top](#table-of-contents)** From 3ff9eba6d460f31db8146762bade4fcc32626762 Mon Sep 17 00:00:00 2001 From: Ryan McDermott Date: Sun, 23 May 2021 11:52:44 -0700 Subject: [PATCH 21/24] Fix `paintCar` example to include `color` as param --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 71896ed4..631db6e8 100644 --- a/README.md +++ b/README.md @@ -180,8 +180,8 @@ const Car = { carColor: "Blue" }; -function paintCar(car) { - car.carColor = "Red"; +function paintCar(car, color) { + car.carColor = color; } ``` @@ -194,8 +194,8 @@ const Car = { color: "Blue" }; -function paintCar(car) { - car.color = "Red"; +function paintCar(car, color) { + car.color = color; } ``` From 384665f8da2de749ad96c694a9e18227cfd08b45 Mon Sep 17 00:00:00 2001 From: Hamed Abdollahi <42994875+hamettio@users.noreply.github.com> Date: Fri, 23 Jul 2021 19:04:42 +0200 Subject: [PATCH 22/24] Persian translation added (Fluent + RTL styled) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 631db6e8..52e2e786 100644 --- a/README.md +++ b/README.md @@ -2381,5 +2381,6 @@ This is also available in other languages: - ![tr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Turkey.png) **Turkish**: [bsonmez/clean-code-javascript](https://github.com/bsonmez/clean-code-javascript/tree/turkish-translation) - ![ua](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Ukraine.png) **Ukrainian**: [mindfr1k/clean-code-javascript-ua](https://github.com/mindfr1k/clean-code-javascript-ua) - ![vi](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Vietnam.png) **Vietnamese**: [hienvd/clean-code-javascript/](https://github.com/hienvd/clean-code-javascript/) +- ![ir](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Iran.png) **Persian**: [hamettio/clean-code-javascript](https://github.com/hamettio/clean-code-javascript) **[⬆ back to top](#table-of-contents)** From 98f1d4a5a3b00c7b201400db6a443817d759859b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eug=C3=A8ne=20d=27Augier?= <101138826+eugene-augier@users.noreply.github.com> Date: Wed, 13 Apr 2022 14:08:10 +0200 Subject: [PATCH 23/24] French translation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 631db6e8..3c06041e 100644 --- a/README.md +++ b/README.md @@ -2365,7 +2365,7 @@ This is also available in other languages: - [alivebao/clean-code-js](https://github.com/alivebao/clean-code-js) - [beginor/clean-code-javascript](https://github.com/beginor/clean-code-javascript) - ![tw](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Taiwan.png) **Traditional Chinese**: [AllJointTW/clean-code-javascript](https://github.com/AllJointTW/clean-code-javascript) -- ![fr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/France.png) **French**: [GavBaros/clean-code-javascript-fr](https://github.com/GavBaros/clean-code-javascript-fr) +- ![fr](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/France.png) **French**: [eugene-augier/clean-code-javascript-fr](https://github.com/eugene-augier/clean-code-javascript-fr) - ![de](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Germany.png) **German**: [marcbruederlin/clean-code-javascript](https://github.com/marcbruederlin/clean-code-javascript) - ![id](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Indonesia.png) **Indonesia**: [andirkh/clean-code-javascript/](https://github.com/andirkh/clean-code-javascript/) - ![it](https://raw.githubusercontent.com/gosquared/flags/master/flags/flags/shiny/24/Italy.png) **Italian**: [frappacchio/clean-code-javascript/](https://github.com/frappacchio/clean-code-javascript/) From 2cab77b8e58dce3f6c418595b7ef70adca1a4258 Mon Sep 17 00:00:00 2001 From: Agil Atakishiyev Date: Sun, 10 Jul 2022 21:05:45 +0400 Subject: [PATCH 24/24] fixed naming --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 631db6e8..e2880d99 100644 --- a/README.md +++ b/README.md @@ -201,9 +201,9 @@ function paintCar(car, color) { **[⬆ back to top](#table-of-contents)** -### Use default arguments instead of short circuiting or conditionals +### Use default parameters instead of short circuiting or conditionals -Default arguments are often cleaner than short circuiting. Be aware that if you +Default parameters are often cleaner than short circuiting. Be aware that if you use them, your function will only provide default values for `undefined` arguments. Other "falsy" values such as `''`, `""`, `false`, `null`, `0`, and `NaN`, will not be replaced by a default value.