Skip to content

tanerceker/clean-code

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 

Repository files navigation

Clean Code

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 edin


Composition 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;
}

About

Clean code for Javascript

Topics

Resources

Stars

Watchers

Forks