Temiz kod her zaman önemseyen biri tarafından yazılmış gibi görünür.
Daha iyi hale getirmek için yapabileceğiniz bariz bir şey yoktur.
— Michael Feathers
Name Casing — Ad Muhafazası
// camelCase
let firstName = "Taner";
let lastName = "Çeker";// PascalCase
class UserAuth {}
class UserSettings {}// snake_case
let user = { first_name: "Taner", last_name: "Çeker" };
// SNAKE_CASE
const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000; // 86400000// kebab-case
let user = { "first-name": "Taner", "last-name": "Çeker" };Meaningful — Anlamlı
const data = { id: 1, name: "Taner" } ❌
const user = { id: 1, name: "Taner" } ✅
// Bağlam'a (Context) bağlı olarak anlamlı ad'lar kullanılmalı.
// Örn. para transfer yapan birini işaret ediyorsak;
// "customer" daha anlamlıdır
const customer = { id: 1, name: "Taner" } ✅Pronounceable — Telaffuz edilebilir
const yyyymmdd = moment().format("YYYY/MM/DD") ❌
const currentData = moment().format("YYYY/MM/DD") ✅Detailed — Detaylı, Açıklayıcı
const days = 12 ❌
const time = 3756 ❌
const daysSinceEventCreation = 12 ✅
const timeSinceLastCheck = 3756 ✅Booleans — Mantıksallar
// is, are, should, has, etc ...
let loading = true ❌
let productsInCart = false ❌
let isLoading = true ✅
let user.hasProductsInCart = false ✅No redundant words — Gereksiz kelimeler yok
// data, info, record, list, etc...
const userData = {} ❌
const productList = [] ❌
const taskInfo = {} ❌
const user = {} ✅
const products = [] ✅
const task = {} ✅Always be explicit — Her zaman açık olun
const daysOfTheWeek = ["Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"]
daysOfTheWeek.forEach(d => { ❌
something(d)
/*
...
...
...
*/
somethingElse(d)
})
daysOfTheWeek.forEach(dayOfTheWeek => { ✅
something(dayOfTheWeek)
/*
...
...
...
*/
somethingElse(dayOfTheWeek)
})Naming constants — Sabitlerin adlandırılması
const MAX_NUMBER_OF_RETRY = 3;
const userName = "Taner";
const maxNumberOfExecutions = 3;
for (let i = 0; i < maxNumberOfExecutions; i++) {
sendMessageByTwitter(userName);
}Function naming — Fonksiyon adlandırması
// Use verbs - Fiilleri kullanın
const saveNewPassword = () => {};
const fetchArticles = () => {};
const isEven = () => {};
// Consistent - Tutarlılık
const getComments = () => {};
const fetchArticles = () => {};
const retrieveCategory = () => {};
// Details - Detaylılık
const saveNewPassword = () => {};
const fetchArticlesByCategoryName = () => {};Keep short functions — Fonksiyonları kısa tutun
// 1. Fonksiyonların ilk kuralı küçük olmaları gerektiğidir.
// 2. İkinci kural ise daha da küçük olmaları gerektiğidir.
// 1. Sadece tek bir şey yapmalı.
async function login(username, password) { ❌
const accessToken = await database.login(username,password)
if (!accessToken) {
throw new Error('Wrong credentials')
}
localStorage.setItem('accessToken', accessToken)
redirectTo("/")
notifyUser("success", e.message)
}
async function login(username, password) { ✅
const accessToken = await database.login(username,password)
if (!accessToken) {
throw new Error('Wrong credentials')
}
localStorage.setItem('accessToken', accessToken)
}
// 2. Diğer fonksiyonların ayıklanması (extract)
function submitLogin(username, password) { ❌
try {
if (username.length < 3) {
throw new Error('Username must be at least 3 characters long')
}
if (password.length < 3) {
throw new Error('Password must be at least 3 characters long')
}
await login(username, password)
redirectTo("/")
notifyUser("success", e.message)
} catch (e) {
console.error(e)
notifyUser("error", e.message)
}
}
function submitLogin(username, password) { ✅
try {
validateLoginFields(username, password)
await login(username, password)
redirectTo("/")
notifyUser("success", e.message)
} catch (e) {
console.error(e)
notifyUser("error", e.message)
}
}
function validateLoginFields(username, password) {
if (username.length < 3) {
throw new Error('Username must be at least 3 characters long')
}
if (password.length < 3) {
throw new Error('Password must be at least 3 characters long')
}
}Parameters management — Parametre yönetimi
// Maksimum iki parametre kuralı
function updateUserAdress(country, city, postalCode, street) { ❌
}
updateUserAdress("France", "Paris", "75000", "rue de la Republique")
function updateUserAdress(country, city) { ✅
}
updateUserAdress("France", "Paris")
// Nesne kullanarak daha fazla parametre kullanılabilir
function updateUserAdress({country, city, postalCode, street}) { ✅
}
updateUserAdress({
country: "France",
city: "Paris",
postalCode: "75000",
street: "rue de la Republique",
})Default values — Varsayılan değerler
function sleep(durationInMilliseconds) { ❌
durationInMilliseconds = durationInMilliseconds ?? 10000
return new Promise(resolve => setTimeout(resolve, durationInMilliseconds))
}
function sleep(durationInMilliseconds = 1000) { ✅
return new Promise(resolve => setTimeout(resolve, durationInMilliseconds))
}
function createTask(config) { ❌
config.title = config.title ?? "Untitled task"
config.category = config.category ?? "Main"
config.isActive = config.isActive ?? true
// ...
}
// Varsayılan nesneler için Object.assign()
const defaultConfig = {
title: 'Untitled task',
category: 'Main',
isActive: true
}
function createTask(rawConfig) { ✅
const config = Object.assign(defaultConfig, rawConfig)
// ...
}
createTask({
title: 'Recording',
category: 'DevTheory'
})Flag parameters — Bayrak parametreleri
// Bayrak (Flag) parametrelerini kullanmayın
function updateUser(isPremium) { ❌
if (isPremium) {
/* ... */
} else {
/* ... */
}
}
if (isPremium) { ✅
updatePremiumUser()
} else {
updateFreeUser()
}
function updatePremiumUser() {
}
function updateFreeUser() {
}
// Tek bir işlem hariç
function updateUser(isPremium) { ✅
something()
/*
...
*/
if (isPremium) {
sendUpdateConfirmationOnTelegram()
} else {
sendUpdateConfirmationOnByMail()
}
}Things to avoid — Kaçınılması gereken şeyler
// Global / üst kapsam (upper-scope) değişkenleri kullanmaktan kaçının
const code = "let x = 5;let y = 10;let z = x + y;"
const lines = splitCodeIntoLines()
console.log(lines) // [ 'let x = 5', 'let y = 10', 'let z = z + y' ]
function splitCodeIntoLines() { ❌
return code.split(";")
}
// Referansların değerini değiştirmekten kaçının
function addItemToCart(cart, item) { ❌
cart.push({ item, date: Date.now() })
}
function addItemToCart(cart, item) { ✅
return [...cart, { item, date: Date.now() }]
}Classes or Functions — Sınıflar veya Fonksiyonlar
// Basit sınıflar yerine basit fonksiyonları tercih edinComposition or Inheritance — Bileşim veya Kalıtım
Kalıtım (Inheritance) → Örn. Kuş bir hayvandır. — Insan bir memelidir. (is-a)
Bileşim (Composition) → Örn. Arabanın bir motoru var. — Araba bir motora sahiptir. (has-a)
// Kalıtım (Inheritance) yerine Bileşimi (Composition) tercih edin
// ilişki türleri: is-a vs has-a
// Kalıtım (Inheritance) (is-a)
class Market {
constructor(symbol) {
this.symbol = symbol;
}
/* ... */
}
class MarketOrder extends Market {
constructor(symbol, price, quantity) {
super(symbol);
this.price = price;
this.quantity = quantity;
}
/* ... */
}
// Bileşim (Composition) (has-a)
class Market {
constructor(symbol) {
this.symbol = symbol;
}
/* ... */
}
class Order {
constructor(price, quantity) {
this.price = price;
this.quantity = quantity;
}
setMarket(symbol) {
this.market = new Market(symbol);
}
/* ... */
}Don't ignore errors — Hataları görmezden gelmeyin
// Hatalar görmezden gelinemez.
// Dış (External) API (Kontrolü size ait olamayan) için
// hata kontrolleri kullanılmalı.
let isLoading = true;
try {
await fetchArticles();
} catch (e) {
notifyUser("Failed to fetch articles");
reportError(e);
} finally {
isLoading = false;
}Use JSdoc for functions — Fonksiyonlar için JSdoc kullanılabilir
/**
* Validates login fields
*
* @param {string} email
* @param {string} password
* @returns {boolean} The boolean returned
* */
function validateLoginFields(email, password) {
if (email.length > 0) {
throw new ValidationError("Email is required");
} else if (password.length > 0) {
throw new ValidationError("Password is required");
}
return true;
}