Kod İnceleme Süreci ve En İyi Pratikler

Yıllar içinde onlarca ekiple çalıştım ve şunu net söyleyebilirim: kod inceleme süreci, bir ekibin yazılım kalitesini belirleyen en kritik pratiklerden biri. Ama çoğu yerde ya hiç yapılmıyor, ya da “tamam gördüm, merge et” şeklinde geçiştiriliyor. Bu yazıda hem süreci nasıl kuracağınızı hem de SonarQube ve ESLint gibi araçları bu sürece nasıl entegre edeceğinizi anlatacağım. Pratik örneklerle, gerçek hayattan çıkmış senaryolarla.

Kod İnceleme Neden Bu Kadar Önemli?

Bir üretim ortamında yaşanan olayların büyük çoğunluğunun kötü kod incelemesinden kaynaklandığını söylesem abartmış olmam. SQL injection açığı, hafıza sızıntısı, yanlış konfigürasyon… Bunların büyük kısmı iyi bir code review süreciyle yakalanabilirdi.

Kod inceleme sadece hata bulmak değil. Aynı zamanda:

  • Bilgi transferi sağlar, ekibin tamamı kod tabanına hakim olur
  • Kod standartlarının otomatik değil, kültürel olarak benimsenmesini sağlar
  • Junior geliştiricilerin büyümesine zemin hazırlar
  • Teknik borcu erken aşamada tespit eder

Ama bu faydaların gerçekleşmesi için sürecin doğru kurulması şart.

Temel Prensipler: Ne Bakıyoruz, Nasıl Bakıyoruz?

Code review sürecine başlamadan önce ekipçe bazı sorulara net cevap vermek gerekiyor.

Ne inceliyoruz?

  • Fonksiyonel doğruluk: Kod yapması gerekeni yapıyor mu?
  • Güvenlik: Açık var mı, input validasyonu eksik mi?
  • Performans: Gereksiz döngüler, N+1 sorgu problemi gibi durumlar
  • Okunabilirlik: Başka biri bu kodu üç ay sonra anlayabilir mi?
  • Test kapsamı: Kritik akışlar test edilmiş mi?

Nasıl bakıyoruz?

Bu kısım çoğu ekipte atlanıyor. Reviewer’ın tutumu en az teknik bilgisi kadar önemli. Eleştiri koda yönelik olmalı, kişiye değil. “Bu yanlış” yerine “Bu durumda şöyle bir sorun çıkabilir, şunu deneyelim mi?” yaklaşımı hem daha yapıcı hem de ekip içi sürtüşmeyi azaltır.

Git Hook ile İlk Savunma Hattı

Kod incelemeye gelmeden önce temel kontrolleri otomatize etmek gerekiyor. Git hooks bu iş için biçilmiş kaftan.

#!/bin/bash
# .git/hooks/pre-commit

echo "Pre-commit kontrolleri başlıyor..."

# ESLint kontrolü
if command -v eslint &> /dev/null; then
    echo "ESLint çalışıyor..."
    git diff --cached --name-only --diff-filter=ACM | grep '.js$|.ts$|.jsx$|.tsx$' | xargs eslint --max-warnings=0
    if [ $? -ne 0 ]; then
        echo "HATA: ESLint hataları bulundu. Commit reddedildi."
        exit 1
    fi
fi

# Büyük dosya kontrolü (5MB üzeri)
git diff --cached --name-only | while read file; do
    if [ -f "$file" ]; then
        size=$(du -k "$file" | cut -f1)
        if [ "$size" -gt 5120 ]; then
            echo "UYARI: $file dosyası 5MB'dan büyük!"
            exit 1
        fi
    fi
done

echo "Tüm kontroller geçildi."
exit 0

Bu hook’u ekip genelinde zorunlu kılmak için core.hooksPath ayarını kullanabilirsiniz:

# Repository seviyesinde hook dizinini ayarla
git config core.hooksPath .githooks

# Hook dosyasını çalıştırılabilir yap
chmod +x .githooks/pre-commit

# Tüm ekibin kullanması için README'ye ekle veya
# onboarding scriptine dahil et

ESLint Konfigürasyonu: Sadece Syntax Değil, Kalite de

ESLint’i çoğu ekip sadece syntax hatası için kullanıyor. Oysa doğru konfigüre edildiğinde çok daha güçlü bir araç.

// .eslintrc.js
module.exports = {
  env: {
    node: true,
    es2022: true,
    jest: true
  },
  extends: [
    'eslint:recommended',
    'plugin:security/recommended',
    'plugin:sonarjs/recommended'
  ],
  plugins: ['security', 'sonarjs'],
  rules: {
    // Karmaşıklık kontrolü - fonksiyon başına max 10 cyclomatic complexity
    'complexity': ['error', 10],
    
    // Fonksiyon uzunluğu
    'max-lines-per-function': ['warn', { max: 50 }],
    
    // Güvenlik: eval kullanımı yasak
    'no-eval': 'error',
    
    // Console.log production'da sorun çıkarır
    'no-console': ['warn', { allow: ['warn', 'error'] }],
    
    // Async/await hata yönetimi
    'no-return-await': 'error',
    
    // Duplicate kod tespiti (sonarjs plugin)
    'sonarjs/no-duplicate-string': ['error', 3],
    'sonarjs/cognitive-complexity': ['error', 15]
  }
};

eslint-plugin-security ve eslint-plugin-sonarjs eklentilerini mutlaka kurun. Özellikle security plugin’i, eval(), dinamik require(), path traversal gibi güvenlik açıklarını statik analiz aşamasında yakalar.

# Gerekli paketleri kur
npm install --save-dev eslint eslint-plugin-security eslint-plugin-sonarjs

# Tüm proje üzerinde çalıştır ve rapor üret
eslint . --format json --output-file eslint-report.json

# Sadece değişen dosyaları analiz et (CI için hızlı)
git diff --name-only HEAD~1 HEAD | grep '.js$' | xargs eslint

SonarQube Kurulumu ve CI Entegrasyonu

ESLint güzel ama proje büyüdükçe merkezi bir analiz platformuna ihtiyaç duyuyorsunuz. SonarQube burada devreye giriyor. Docker ile hızlıca ayağa kaldırabilirsiniz:

# SonarQube'u Docker ile başlat
docker run -d 
  --name sonarqube 
  -p 9000:9000 
  -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true 
  -v sonarqube_data:/opt/sonarqube/data 
  -v sonarqube_logs:/opt/sonarqube/logs 
  sonarqube:community

# İlk açılışta admin/admin ile giriş yap
# Sonra hemen şifreyi değiştir!

# sonar-scanner kurulumu
wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip
unzip sonar-scanner-cli-5.0.1.3006-linux.zip
export PATH=$PATH:/opt/sonar-scanner-5.0.1.3006-linux/bin

Proje kök dizinine sonar-project.properties dosyası oluşturun:

# sonar-project.properties
sonar.projectKey=my-backend-api
sonar.projectName=Backend API Servisi
sonar.projectVersion=1.0

sonar.sources=src
sonar.tests=tests
sonar.exclusions=**/node_modules/**,**/dist/**,**/*.test.js

# Test coverage raporu (Jest ile üretilen)
sonar.javascript.lcov.reportPaths=coverage/lcov.info

# Kalite kapısı - bu eşiklerin altı merge edilemez
sonar.qualitygate.wait=true

GitLab CI ile Tam Entegrasyon

İşin güzel kısmı burası. SonarQube ve ESLint’i CI/CD pipeline’ına bağladığınızda, kalite kontrol otomatik hale geliyor. Kimse “gözden kaçtı” diyemiyor.

# .gitlab-ci.yml
stages:
  - lint
  - test
  - quality
  - review

variables:
  SONAR_HOST_URL: "http://sonarqube.internal:9000"

eslint-check:
  stage: lint
  image: node:20-alpine
  cache:
    paths:
      - node_modules/
  script:
    - npm ci
    - npx eslint . --format gitlab
  artifacts:
    reports:
      codequality: gl-code-quality-report.json
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

unit-tests:
  stage: test
  image: node:20-alpine
  script:
    - npm ci
    - npm test -- --coverage --coverageReporters=lcov
  artifacts:
    paths:
      - coverage/
    expire_in: 1 day

sonarqube-analysis:
  stage: quality
  image:
    name: sonarsource/sonar-scanner-cli:latest
    entrypoint: [""]
  dependencies:
    - unit-tests
  script:
    - sonar-scanner
        -Dsonar.login=$SONAR_TOKEN
        -Dsonar.pullrequest.key=$CI_MERGE_REQUEST_IID
        -Dsonar.pullrequest.branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
        -Dsonar.pullrequest.base=$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
  allow_failure: false

allow_failure: false kritik. SonarQube kalite kapısını geçemezse merge bloklanıyor. Bu olmadan sürecin hiçbir anlamı yok.

Code Review Süreci: Adım Adım

Araçları kurduk, şimdi süreci konuşalım. Araçlar olmadan süreç işlemez, süreç olmadan araçlar yalnızca güzel raporlar üretir.

Pull Request / Merge Request Açılışı

PR açılırken şu bilgiler mutlaka olmalı:

  • Ne değişti ve neden? (Bağlı issue linki)
  • Nasıl test edildi?
  • Screenshot veya API response örneği (UI/API değişikliklerinde)
  • Reviewer için dikkat edilmesi gereken noktalar

PR template kullanın. GitLab ve GitHub’da .gitlab/merge_request_templates/ ve .github/pull_request_template.md ile bu zorunlu hale getirilebilir.

Reviewer Ataması

Kimsenin review’una bakmaması, en yaygın başarısızlık noktası. Bu konuda birkaç kural koyun:

  • Her PR en az bir senior, bir junior reviewer gerektirsin
  • PR sahibi kendi PR’ına review yapamaz (GitLab’da branch protection ile zorunlu kılınabilir)
  • Review SLA’sı belirleyin: iş günü içinde 4 saat

Review Yorumları Standardizasyonu

Yorumları kategorize etmek, önceliklendirmeyi kolaylaştırır. Google’ın kullandığı bir yaklaşımı biz de uyarladık:

  • [BLK] (Blocker): Merge edilemez, mutlaka düzeltilmeli
  • [MAJ] (Major): Önemli, düzeltilmeli ama kritik değil
  • [MIN] (Minor): Küçük öneri, yapılması güzel olur
  • [NIT] (Nit): Stil, format gibi ufak detay
  • [SOA] (Soru): Sormak için, blocker değil

Örnek: [BLK] Bu endpoint'te authentication kontrolü eksik, kimliği doğrulanmamış kullanıcılar erişebilir.

Quality Gate Konfigürasyonu

SonarQube’de quality gate tanımlamak, “geçer not” belirlemek gibi. Varsayılan ayarlar genellikle yeterli değil, projeye göre özelleştirin.

# SonarQube API ile quality gate oluşturma
curl -u admin:$SONAR_ADMIN_PASSWORD 
  -X POST 
  "$SONAR_HOST_URL/api/qualitygates/create" 
  -d "name=Custom Gate"

# Koşul ekle: yeni kod için coverage %80 altındaysa fail
curl -u admin:$SONAR_ADMIN_PASSWORD 
  -X POST 
  "$SONAR_HOST_URL/api/qualitygates/create_condition" 
  -d "gateName=Custom Gate" 
  -d "metric=new_coverage" 
  -d "op=LT" 
  -d "error=80"

# Koşul ekle: yeni blocker sayısı 0'dan fazlaysa fail
curl -u admin:$SONAR_ADMIN_PASSWORD 
  -X POST 
  "$SONAR_HOST_URL/api/qualitygates/create_condition" 
  -d "gateName=Custom Gate" 
  -d "metric=new_blocker_violations" 
  -d "op=GT" 
  -d "error=0"

# Koşul ekle: duplicate kod %3 üzerindeyse fail
curl -u admin:$SONAR_ADMIN_PASSWORD 
  -X POST 
  "$SONAR_HOST_URL/api/qualitygates/create_condition" 
  -d "gateName=Custom Gate" 
  -d "metric=new_duplicated_lines_density" 
  -d "op=GT" 
  -d "error=3"

Gerçek Hayat: Kod İnceleme Sırasında Sık Karşılaşılan Sorunlar

Sorun 1: “Çok büyük PR”

500 satır değişiklik içeren bir PR’ı kim review eder? Kimse. Kural koyun: PR başına maksimum 300-400 satır değişiklik. Özellik büyükse feature flag ile parçalayın.

Sorun 2: “Sadece araç bulduğu şeyleri fix’liyoruz”

ESLint ve SonarQube otomatik olarak bulamazlar: iş mantığı hataları, yetersiz test senaryoları, doğru algoritma seçimi. Araçların geçtikleri ile işin bittiğini düşünmek tehlikeli. Araçlar otomatize edilebilen kontrolleri alır üstünden, asıl düşünme işi insanda kalır.

Sorun 3: “Review yapan her şeyi onaylıyor”

Rubber stamp review denen bu durum, süreci anlamsız kılar. Reviewer’ların sorgulamaktan çekinmediği, psikolojik güvenliğin yüksek olduğu bir ortam kurmak gerekiyor. Bunu kültürel olarak yaratmak zaman alır ama review metrikleri takip ederek (yorumlanmış PR oranı, yorum başına düzeltme oranı) görünür kılabilirsiniz.

Sorun 4: “Herkes aynı dosyalara bakıyor”

Ownership matrisi olmayan projelerde herkes kendi alanını review ediyor, kimse uç noktalara bakmıyor. CODEOWNERS dosyası bu sorunu çözer:

# .github/CODEOWNERS veya .gitlab/CODEOWNERS
# Her değişiklik ilgili ekibin otomatik review'una girer

# Auth modülü - güvenlik ekibinin onayı şart
/src/auth/**        @security-team @backend-lead

# Database migrasyonları - DB ekibi onaylamalı
/migrations/**      @db-team

# CI/CD konfigürasyonu - DevOps onaylamalı
/.gitlab-ci.yml     @devops-team
/Dockerfile*        @devops-team

# Frontend komponentleri
/src/components/**  @frontend-team

Metrik Takibi: Süreç İyileştirme için Veri

Neyi ölçmüyorsanız, onu iyileştiremezsiniz. Code review sürecinde takip etmeniz gereken metrikler:

  • Review süresi (Time to Review): PR açılmasından ilk yorum gelene kadar geçen süre. Hedef: 4 saat iş günü içinde.
  • Review döngüsü (Review Cycles): Ortalama kaç round review gerekiyor? 3’ün üzeriyse tasarım aşamasında sorun var demek.
  • Defect kaçış oranı (Defect Escape Rate): Code review’dan geçip production’a ulaşan bug sayısı. Bu düşmeli.
  • SonarQube teknik borç trendi: Her sprint sonunda toplam teknik borç artıyor mu, azalıyor mu?

Bu metrikleri GitLab’ın yerleşik analytics’i veya SonarQube raporlarıyla takip edebilirsiniz. Daha detaylı analiz için Elasticsearch + Kibana kombosuna GitLab webhook’larını bağlamak işe yarıyor, ama bu ayrı bir yazı konusu.

Küçük Ekipler İçin Pragmatik Yaklaşım

Her şey güzel de, 3 kişilik bir startup ekibine “2 reviewer zorunlu” kuralı uygulamak gerçekçi değil. Küçük ekipler için pragmatik bir set:

  • Pre-commit hook ile ESLint zorunlu
  • CI’da SonarQube analizi çalışsın ama sadece blocker seviyesindekiler pipeline’ı durdursun
  • Her PR en az bir review gerektirsin, ama eş zamanlı iki kişi değil
  • Haftalık 30 dakikalık “teknik borç” toplantısı: SonarQube raporuna birlikte bakın

Mükemmel süreç, işlemeyen süreçten iyidir. Küçük başlayıp olgunlaştırmak, büyük süreç kurup kimsenin uymadığını görmekten çok daha sağlıklı.

Sonuç

Kod inceleme süreci, ESLint kurup SonarQube dashboard’una bakmaktan ibaret değil. Araçlar gerekli ama yeterli değil. Asıl mesele, ekibin “kodu birlikte sahiplenmesi” kültürünü oluşturmak.

Bunu yaparken şu sırayla ilerleyin: önce otomasyonu kurun (git hooks, CI entegrasyonu), sonra süreci netleştirin (PR template, review SLA, yorum standardı), ardından kültürü besleyin (yapıcı geri bildirim, psikolojik güvenlik, metrik paylaşımı).

SonarQube size teknik borcunuzu söyler, ESLint potansiyel açıkları işaretler, ama hangi açığın gerçekten kritik olduğuna, hangi refactoring’in önce yapılması gerektiğine ve ekibin moral motivasyonunun nasıl yönetileceğine karar verecek olan hala insanlar. Araçları doğru kullanın, ama süreci insan merkezli tutun.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir