Giriş
FreeCodeCamp bir öğrenme platformundan fazlasıdır; binlerce katkıda bulunanı ve milyonlarca satır JavaScript ve TypeScript içeren büyük, açık kaynaklı bir kod tabanıdır. Böyle karmaşık bir projeyi yönetmek, gerilemeleri (regressions) önlemek ve güvenilirliği korumak için tutarlı mimari kalıplar, katı adlandırma kuralları ve kapsamlı testler gerektirir.
Bu makalede, FreeCodeCamp'ten çıkarılan en etkili kod inceleme kurallarını sunuyoruz. Her kural; dikkatli tasarımın, tutarlı veri akışının ve sağlam hata yönetiminin, büyük projelerin düzenli kalmasına ve zaman içinde küçük hataların (bug) riskini azaltmasına nasıl yardımcı olabileceğini göstermektedir.
Zorluklar
FreeCodeCamp'te kod kalitesini korumak, büyük JavaScript ve TypeScript kod tabanı ve binlerce katkıda bulunan nedeniyle zordur. Tutarlı kalıpları, öngörülebilir veri akışını ve güvenilir işlevselliği sağlamak; yapılandırılmış inceleme kuralları ve otomatik kontroller gerektirir.
Başlıca zorluklar arasında tutarsız kodlama kalıpları, sıkı bir şekilde birbirine bağlı (tightly coupled) eski modüller, düzensiz test kapsamı, belgelerin güncelliğini yitirmesi ve yüksek hacimli pull request'ler yer almaktadır.
Net standartlar, otomatik doğrulama ve dikkatli kod incelemesi, proje büyüdükçe kod tabanının sürdürülebilir, kararlı ve ölçeklenebilir kalmasına yardımcı olur.
Bu kuralların önemi nedir?
Tutarlı kod inceleme kuralları; tek tip modül yapısını, adlandırma kurallarını ve öngörülebilir veri akışlarını zorunlu kkarak sürdürülebilirliği artırır, böylece testleri daha güvenilir ve bağımlılıkları takip etmeyi daha kolay hale getirir.
Ayrıca girdi doğrulama, hata yönetimi ve kontrollü yan etkiler (side effects) yoluyla güvenliği artırırken; yeni katkıda bulunanların modül sorumluluklarını ve entegrasyon noktalarını hızlı bir şekilde anlamasına yardımcı olarak adaptasyon sürecini (onboarding) hızlandırırlar.
Bu kurallara bağlam oluşturmak
Bu kurallar, FreeCodeCamp'in deposundan ve pull request'lerinden çıkarılmış olup; kararlılığı ve sürdürülebilirliği etkileyen, belirsiz veri akışı, eksik hata yönetimi ve tutarsız testler gibi yinelenen sorunları yansıtmaktadır.
Her kural somut bir tuzağı vurgular, bunun performans, netlik veya güvenilirlik üzerindeki etkisini açıklar ve ❌ uyumlu olmayan ile ✅ uyumlu JavaScript veya TypeScript örneklerini içerir.
1. TypeScript'te any türünün aşırı kullanımından kaçının
TypeScript'te any türünü kullanmaktan kaçının. Tür güvenliğini sağlamak ve çalışma zamanı (runtime) hatalarını önlemek için değişkenler, fonksiyon parametreleri ve dönüş değerleri için her zaman doğru ve açık türler tanımlayın.
❌ Kural dışı:
let userData: any = fetchUserData();✅ Kurallara uygun:
interface UserData {
id: string;
name: string;
email: string;
}
let userData: UserData = fetchUserData();Neden önemli?: Herhangi bir "any" tipi kullanmak, TypeScript'in tip denetimini devre dışı bırakır; bu da çalışma zamanı (runtime) hatalarının oluşmasına yol açabilir, kodun sürdürülebilirliğini ve güvenilirliğini azaltır. Açık (explicit) tipler, kodun daha güvenli olmasını ve diğer geliştiriciler tarafından daha kolay anlaşılmasını sağlar.
2. Kısaltmalar yerine açıklayıcı değişken adları tercih edin
Her zaman net ve açıklayıcı değişken adları kullanın. Kodun anlamını gizleyen kısaltmalardan veya anlaşılmaz adlardan kaçının.
❌ Kural dışı:
const usr = getUser();✅ Kurallara uygun:
const user = getUser();Neden önemli?: Açıklayıcı değişken adları kodun okunmasını, anlaşılmasını ve sürdürülmesini kolaylaştırır. Kötü isimlendirme, geliştiricilerin kafasını karıştırabilir ve hata (bug) riskini artırabilir.
3. Derinlemesine iç içe geçmiş döngülerden veya koşullardan kaçının
Döngülerde veya koşullarda derin iç içe geçmeleri önlemek için kodu yeniden düzenleyin (refactor). Mantığı sadeleştirmek (flatten) amacıyla erken dönüşler (early returns) veya yardımcı fonksiyonlar (helper functions) kullanın.
❌ Kural dışı:
if (user) {
if (user.isActive) {
if (user.hasPermission) {
// İşlemi gerçekleştir
}
}
}✅ Kurallara uygun:
if (!user) return;
if (!user.isActive) return;
if (!user.hasPermission) return;
// İşlemi gerçekleştir
processUserAction(user);Neden önemli?: Derinlemesine iç içe geçmiş mantık yapılarının takip edilmesi, sürdürülmesi ve test edilmesi zordur. Özellikle olumsuz senaryolar ve erken başarısızlık durumları için birim testleri (unit test) yazmayı zorlaştırır. Erken dönüşlerle kontrol akışını düzleştirmek, kodun mantığını kavramayı kolaylaştırır, test kapsamını (test coverage) artırır ve gizli uç durum (edge-case) hatalarının olasılığını azaltır.
4. Kod tabanı genelinde tutarlı hata yönetimi sağlayın
Her zaman tutarlı bir hata yönetimi uygulayın. İstisnaları (exceptions) tekdüze bir şekilde ele almak için merkezi hata fonksiyonları veya standartlaştırılmış kalıplar kullanın.
❌ Kural dışı:
try {
// Some code
} catch (e) {
console.error(e);
}✅ Kurallara uygun:
try {
// Some code
} catch (error) {
logError(error);
throw new CustomError('An error occurred', { cause: error });
}Neden önemli?: Tutarlı hata yönetimi, hata ayıklamayı (debugging) kolaylaştırır, beklenmeyen davranışları önler ve uygulama genelinde güvenilirliği garanti eder.
5. Yapılandırma değerlerini koda doğrudan (hardcode) gömmekten kaçının
URL'ler, bağlantı noktaları (ports) veya gizli anahtarlar gibi ortama özel değerleri koda doğrudan yazmayın. Her zaman yapılandırma dosyaları veya ortam değişkenleri (environment variables) kullanın.
❌ Kural dışı:
const apiUrl = 'https://api.example.com';✅ Kurallara uygun:
const apiUrl = process.env.API_URL;Neden önemli?: Doğrudan koda yazılan değerler esnekliği azaltır, kodu daha az güvenli hale getirir ve farklı ortamlardaki dağıtımları (deployment) karmaşıklaştırır. Yapılandırma kullanmak, sürdürülebilirliği ve güvenliği sağlar.
6. Fonksiyonları tek bir sorumluluğa odaklı tutun
Her fonksiyonun tek ve iyi tanımlanmış bir görev gerçekleştirdiğinden emin olun. Birden fazla sorumluluğu yöneten fonksiyonlardan kaçının; çünkü bu durum kafa karışıklığına ve bakım zorluğuna yol açabilir.
❌ Kural dışı:
function processUserData(user) {
const validatedUser = validateUser(user);
saveUserToDatabase(validatedUser);
sendWelcomeEmail(validatedUser);
}✅ Kurallara uygun:
function validateUser(user) {
// doğrulama mantığı
}
function saveUserToDatabase(user) {
// kaydetme mantığı
}
function sendWelcomeEmail(user) {
// e-posta gönderme mantığı
}Neden önemli?: Tek bir sorumluluğa sahip fonksiyonların test edilmesi, hata ayıklanması ve bakımı daha kolaydır. Kodun yeniden kullanılabilirliğini destekler ve okunabilirliği artırır.
7. Sihirli sayılar (magic numbers) kullanmaktan kaçının
Kodun netliğini ve sürdürülebilirliğini artırmak için sihirli sayıları adlandırılmış sabitlerle (named constants) değiştirin.
❌ Kural dışı:
const area = length * 3.14159 * radius * radius;✅ Kurallara uygun:
const PI = 3.14159;
const area = length * PI * radius * radius;Neden önemli?: Sihirli sayılar (magic numbers) kodun anlamını anlaşılmaz hale getirebilir ve gelecekteki değişiklikleri hataya açık kılabilir. İsimlendirilmiş sabitler (named constants) bağlam sağlar ve hata (bug) riskini azaltır.
8. Global değişken kullanımını en aza indirin
Kod tabanındaki bağımlılıkları ve olası çakışmaları azaltmak için global değişkenlerin kullanımını sınırlandırın.
❌ Kural dışı:
let user = { name: 'Alice' };
function greetUser() {
console.log(`Hello, ${user.name}`);
}✅ Kurallara uygun:
function greetUser(user) {
console.log(`Hello, ${user.name}`);
}
const user = { name: 'Alice' };
greetUser(user);Neden önemli?: Global değişkenler gizli bağımlılıklar ve öngörülemeyen yan etkiler yaratabilir. Verilerin nereden geldiğini veya kod tabanı boyunca nasıl değiştiğini izlemeyi zorlaştırırlar. Verileri fonksiyon parametreleri aracılığıyla açıkça iletmek, veri akışını net ve kontrollü tutar; bu da modülerliği, hata ayıklamayı (debugging) ve uzun vadeli sürdürülebilirliği artırır.
9. Dize birleştirme için şablon değişmezleri (template literals) kullanın
Daha iyi okunabilirlik ve performans için dize birleştirme (string concatenation) yerine şablon değişmezlerini tercih edin.
❌ Kural dışı:
const message = 'Merhaba, ' + user.name + '! ' + user.notifications + ' yeni bildiriminiz var.';✅ Kurallara uygun:
const message = `Hello, ${user.name}! You have ${user.notifications} new notifications.`;Neden önemli?: Şablon değişmezleri, özellikle karmaşık dizelerle veya çok satırlı içerikle çalışırken daha temiz bir sözdizimi sağlar ve okunabilirliği artırır.
10. Doğru girdi doğrulama (input validation) uygulayın
Sisteme geçersiz verilerin girmesini önlemek ve güvenliği artırmak için kullanıcı girdilerini her zaman doğrulayın.
❌ Kural dışı:
function processUserInput(input) {
// işleme mantığı
}✅ Kurallara uygun:
function validateInput(input) {
if (typeof input !== 'string' || input.trim() === '') {
throw new Error('Invalid input');
}
}
function processUserInput(input) {
validateInput(input);
// processing logic
}Neden önemli?: Girdi doğrulama; hataları önlemek, veri bütünlüğünü sağlamak ve enjeksiyon saldırıları gibi güvenlik açıklarına karşı korunmak için çok önemlidir.
11. Her pull request için tek bir mantıksal değişiklik yapın
Her pull request'in (PR) tek bir mantıksal değişiklik veya özellik uyguladığından emin olun; ilgili olmayan düzeltmeleri, yeniden düzenlemeleri (refactor) ve yeni özellik eklemelerini tek bir PR'da birleştirmekten kaçının.
❌ Kural dışı:
# "Fix login + update homepage"
--- auth.js
+ if (!user) throw new Error('User not found');
--- HomePage.js
- <button>Start</button>
+ <button>Begin Journey</button>✅ Uyumlu: (diff)
# PR 1: Fix login validation
+ if (!user) throw new Error('User not found');
# PR 2: Update homepage button
+ <button>Begin Journey</button>Neden önemli?: Küçük ve odaklanmış PR'lar kod incelemesini (code review) basitleştirir, istenmeyen yan etki riskini azaltır ve birleştirme döngülerini hızlandırır. Yapay zeka araçları, linter'ların belirleyemediği bir durum olan, aynı PR içinde ilgili olmayan dosyaların, modüllerin veya alanların değiştiğini tespit edebilir.
12. API'ler ve servisler için etki alanına (domain) dayalı isimlendirme kullanın
API'leri, servisleri ve modülleri iş alanına (business domain) göre adlandırın (ör. handler1.doIt yerine challengeService.createSubmission); isimler varlığı (entity) ve eylemi net bir şekilde yansıtmalıdır.
❌ Kural dışı:
// backend/services/handler.js
export async function doIt(data) {
return await process(data);
}
// routes/index.js
router.post('/submit', handler.doIt);✅ Kurallara uygun:
// backend/services/challengeService.js
export async function createSubmission({ userId, challengeId, answer }) {
return await challengeModel.create({ userId, challengeId, answer });
}
// routes/challenges.js
router.post('/submissions', challengeService.createSubmission);Neden önemli?: Etki alanına dayalı isimlendirme, kodu kendi kendini belgeleyen (self-documenting) hale getirir, yeni katılımcılar için netlik sağlar ve iş mantığıyla uyum oluşturur. Yalnızca anlamsal bağlamın (varlık adları, servis katmanları) farkında olan bir yapay zeka, modüller genelindeki uyumsuz veya genel isimlendirmeleri tespit edebilir.
13. Testlerin hataları ve sınır durumlarını (edge cases) kapsadığından emin olun
Yalnızca "mutlu yolu" (happy path) değil; hata durumlarını, sınır durumlarını ve uç değerleri de test edin; her kritik modülün hem olumlu hem de olumsuz testlere sahip olduğunu onaylayın.
❌ Kural dışı:
describe('login', () => {
it('should succeed with correct credentials', async () => { … });
});✅ Kurallara uygun:
describe('login', () => {
it('should succeed with correct credentials', async () => { … });
it('should fail with incorrect password', async () => { … });
it('should lock account after 5 failed attempts', async () => { … });
});Neden önemli?: İş açısından kritik mantık, genellikle geçersiz girdiler, zaman aşımı (timeout) veya başarısız oturum açma gibi sınır durumları gözden kaçırıldığında bozulur. Hem başarı hem de hata yollarını test etmek, uygulamanın gerçek dünya koşullarında güvenilir bir şekilde çalışmasını sağlar ve ileride yakalanması zor olan gerilemeleri (regression) önler.
14. Katmanları karıştırmayın: UI bileşenleri iş mantığı içermemelidir
UI bileşenlerini (React, front-end) iş mantığından ve veri tabanı/servis çağrılarından arındırın; bu görevleri özel servisler veya hook'lara devredin.
❌ Kural dışı:
// FreeCodeCamp-style
function CurriculumCard({ user, challenge }) {
if (!user.completed.includes(challenge.id)) {
saveCompletion(user.id, challenge.id);
}
return <Card>{challenge.title}</Card>;
}✅ Kurallara uygun:
function CurriculumCard({ user, challenge }) {
return <Card>{challenge.title}</Card>;
}
// In service:
async function markChallengeComplete(userId, challengeId) {
await completionService.create({ userId, challengeId });
}Neden önemli?: İş mantığının UI bileşenlerine karıştırılması katmanlar arasındaki sınırları belirsizleştirir ve gelecekteki değişiklikleri riskli hale getirir. Ayrıca front-end geliştiricilerini backend mantığını anlamaya zorlar ve işbirliğini yavaşlatır. Sorumlulukların ayrı tutulması, her katmanın bağımsız olarak gelişmesini sağlar ve yeniden düzenleme (refactoring) sırasında küçük hataların (bug) ortaya çıkma riskini azaltır.
Sonuç
FreeCodeCamp'in repository'sini analiz ederek, devasa kod tabanının düzenli, okunabilir ve sürdürülebilir kalmasına yardımcı olan pratik kod inceleme (code review) kuralları çıkardık. Bu 20 kural, herhangi bir otomatik araç tarafından zorunlu kılınmasa da, yıllar süren katkılardan elde edilen gerçek pratikleri yansıtmaktadır.
Bu dersleri kendi projelerinizde uygulamak netliği artırabilir, hataları azaltabilir ve işbirliğini daha akıcı hale getirebilir. Kodunuzu güvenli bir şekilde ölçeklendirmek için sağlam bir temel oluşturarak projenin büyümesiyle birlikte kodun güvenilir ve üzerinde çalışılması kolay kalmasını sağlarlar.
Kod incelemesi yalnızca sözdizimi (syntax) kontrol etmekten ibaret değildir; zaman içinde kodunuzun kalitesini ve bütünlüğünü korumakla ilgilidir. FreeCodeCamp gibi olgun bir açık kaynak projesinden ders almak, geliştiricilere herhangi bir kod tabanını iyileştirmek için somut rehberlik sunar.

