Clean Code: Junior Geliştiriciler için 50 Soru ve Cevap (Java Örnekleri ile)



Bu doküman, junior Java geliştiricileri için clean code prensiplerini açıklayan 50 soru ve cevabı içermektedir. Her soru, pratik Java kod örnekleri ve gerçek dünya senaryoları ile desteklenmektedir.

1. Clean Code nedir ve neden önemlidir?

Clean code, okunması, anlaşılması ve bakımı kolay olan kod anlamına gelir. Önemlidir çünkü:

  • Geliştirme süresini kısaltır
  • Hata ayıklamayı kolaylaştırır
  • Kodun ömrünü uzatır
  • Takım çalışmasını iyileştirir

Örnek:

java
// Kötü kod public int x(int a, int b) { return a + b; } // Clean code public int sum(int firstNumber, int secondNumber) { return firstNumber + secondNumber; }

2. Anlamlı isimlendirme neden önemlidir?

Anlamlı isimlendirme, kodun okunabilirliğini ve anlaşılabilirliğini artırır. İyi isimlendirilmiş değişkenler, fonksiyonlar ve sınıflar, kodun ne yaptığını açıkça ifade eder.

Örnek:

java
// Kötü isimlendirme int d; // Elapsed time in days // İyi isimlendirme int elapsedTimeInDays;

3. DRY (Don't Repeat Yourself) prensibi nedir?

DRY prensibi, kod tekrarından kaçınmayı önerir. Her bilgi parçası ve mantık, sistem içinde tek ve net bir temsile sahip olmalıdır.

Örnek:

java
// DRY prensibine uymayan kod public void sendEmailToAdmin() { // E-posta gönderme kodu } public void sendEmailToUser() { // Aynı e-posta gönderme kodu } // DRY prensibine uyan kod public void sendEmail(String recipient) { // E-posta gönderme kodu }

4. SOLID prensipleri nelerdir?

SOLID, beş temel nesne yönelimli tasarım prensibinin kısaltmasıdır:

  • Single Responsibility Principle (SRP)
  • Open-Closed Principle (OCP)
  • Liskov Substitution Principle (LSP)
  • Interface Segregation Principle (ISP)
  • Dependency Inversion Principle (DIP)

Bu prensipler, daha sürdürülebilir ve esnek yazılımlar geliştirmeye yardımcı olur.

5. Single Responsibility Principle (SRP) nedir?

SRP, bir sınıfın yalnızca bir sorumluluğu olması gerektiğini söyler. Bir sınıfın değişmesi için sadece bir nedeni olmalıdır.

Örnek:

java
// SRP'ye uymayan kod public class User { public void saveUser() { /* ... */ } public void sendEmail() { /* ... */ } } // SRP'ye uyan kod public class User { public void saveUser() { /* ... */ } } public class EmailService { public void sendEmail(User user) { /* ... */ } }

6. Open-Closed Principle (OCP) nedir?

OCP, yazılım varlıklarının (sınıflar, modüller, fonksiyonlar vb.) genişletmeye açık, ancak değiştirmeye kapalı olması gerektiğini belirtir.

Örnek:

java
// OCP'ye uymayan kod public class Rectangle { public double width; public double height; } public class AreaCalculator { public double calculateArea(Rectangle rectangle) { return rectangle.width * rectangle.height; } } // OCP'ye uyan kod public interface Shape { double calculateArea(); } public class Rectangle implements Shape { private double width; private double height; @Override public double calculateArea() { return width * height; } } public class Circle implements Shape { private double radius; @Override public double calculateArea() { return Math.PI * radius * radius; } }

7. Liskov Substitution Principle (LSP) nedir?

LSP, alt sınıfların, üst sınıflarının yerine geçebilmesi gerektiğini belirtir. Yani, bir programda herhangi bir üst sınıf nesnesi kullanıldığında, bu nesne alt sınıf nesneleriyle değiştirilebilmelidir ve program hala doğru çalışmalıdır.

Örnek:

java
// LSP'ye uyan kod public class Bird { public void fly() { System.out.println("Kuş uçuyor"); } } public class Sparrow extends Bird { @Override public void fly() { System.out.println("Serçe uçuyor"); } } // LSP'ye uymayan kod public class Ostrich extends Bird { @Override public void fly() { throw new UnsupportedOperationException("Devekuşları uçamaz"); } }

8. Interface Segregation Principle (ISP) nedir?

ISP, istemcilerin kullanmadıkları arayüzlere bağımlı olmaması gerektiğini belirtir. Büyük arayüzler daha küçük ve spesifik arayüzlere bölünmelidir.

Örnek:

java
// ISP'ye uymayan kod public interface Worker { void work(); void eat(); void sleep(); } // ISP'ye uyan kod public interface Workable { void work(); } public interface Eatable { void eat(); } public interface Sleepable { void sleep(); } public class Human implements Workable, Eatable, Sleepable { @Override public void work() { /* ... */ } @Override public void eat() { /* ... */ } @Override public void sleep() { /* ... */ } } public class Robot implements Workable { @Override public void work() { /* ... */ } }

9. Dependency Inversion Principle (DIP) nedir?

DIP, yüksek seviyeli modüllerin düşük seviyeli modüllere bağımlı olmaması gerektiğini belirtir. Her ikisi de soyutlamalara bağlı olmalıdır.

Örnek:

java
// DIP'ye uymayan kod public class LightBulb { public void turnOn() { System.out.println("LightBulb turned on"); } public void turnOff() { System.out.println("LightBulb turned off"); } } public class Switch { private LightBulb bulb; public Switch() { bulb = new LightBulb(); } public void operate() { // Switch logic } } // DIP'ye uyan kod public interface Switchable { void turnOn(); void turnOff(); } public class LightBulb implements Switchable { @Override public void turnOn() { System.out.println("LightBulb turned on"); } @Override public void turnOff() { System.out.println("LightBulb turned off"); } } public class Switch { private Switchable device; public Switch(Switchable device) { this.device = device; } public void operate() { // Switch logic } }

10. Fonksiyonlar nasıl temiz yazılır?

Temiz fonksiyonlar şu özelliklere sahip olmalıdır:

  • Kısa olmalı (genellikle 20 satırdan az)
  • Tek bir iş yapmalı
  • Anlamlı isimlere sahip olmalı
  • Az sayıda parametre almalı (ideal olarak 3 veya daha az)
  • Yan etkilerden kaçınmalı

Örnek:

java
// Temiz olmayan fonksiyon public void processUserData(User user) { if (user.isActive()) { user.updateLastLoginDate(); if (user.getLoginCount() > 5) { user.setVipStatus(true); } sendWelcomeEmail(user); updateUserStats(user); } } // Temiz fonksiyon public void processActiveUser(User user) { updateUserLoginInfo(user); checkAndUpdateVipStatus(user); sendWelcomeEmail(user); updateUserStats(user); } private void updateUserLoginInfo(User user) { user.updateLastLoginDate(); } private void checkAndUpdateVipStatus(User user) { if (user.getLoginCount() > 5) { user.setVipStatus(true); } }

11. Yorum yazma konusunda en iyi uygulamalar nelerdir?

Yorum yazarken dikkat edilmesi gereken noktalar:

  • Kodu açıklamak yerine, kodu daha anlaşılır hale getirmeye çalışın
  • Gereksiz yorumlardan kaçının
  • Yorum yerine açıklayıcı değişken ve fonksiyon isimleri kullanın
  • Karmaşık algoritmaları veya iş mantığını açıklamak için yorumlar kullanın
  • Düzenli olarak yorumları güncelleyin

Örnek:

java
// Kötü yorum kullanımı // Kullanıcının yaşını kontrol et if (user.getAge() >= 18) { // ... } // İyi kod (yorum gerektirmez) if (user.isAdult()) { // ... } // İyi yorum kullanımı // Karmaşık regex açıklaması // Bu regex e-posta adreslerini doğrular: // - Kullanıcı adı: Harf, rakam, nokta, tire ve alt çizgi içerebilir // - @ işareti // - Domain: Harf, rakam ve tire içerebilir // - TLD: 2-6 karakter uzunluğunda olmalıdır String emailRegex = "^[\\w.-]+@[\\w-]+\\.\\w{2,6}$";

12. Exception handling nasıl temiz bir şekilde yapılır?

Temiz exception handling için öneriler:

  • Spesifik exceptionları yakala
  • Exceptionları sessizce yutma
  • Exceptionları anlamlı bir şekilde loglama
  • Custom exceptionlar oluşturma
  • Exception mesajlarını açıklayıcı yapma

Örnek:

java
// Temiz olmayan exception handling try { // Riskli operasyon } catch (Exception e) { e.printStackTrace(); } // Temiz exception handling public void riskyOperation() throws CustomException { try { // Riskli operasyon } catch (SpecificException e) { logger.error("Spesifik hata oluştu: " + e.getMessage()); throw new CustomException("İşlem sırasında bir hata oluştu", e); } catch (AnotherSpecificException e) { logger.warn("Başka bir spesifik hata oluştu: " + e.getMessage()); // Hatayı ele al } }

13. Null kontrolü nasıl temiz bir şekilde yapılır?

Null kontrolü için öneriler:

  • Mümkün olduğunca null döndürmekten kaçının
  • Null Object pattern kullanın
  • Optional sınıfını kullanın (Java 8+)
  • Erken return kullanın

Örnek:

java
// Temiz olmayan null kontrolü public String getUserName(User user) { if (user != null) { String name = user.getName(); if (name != null) { return name; } else { return "Unknown"; } } return "Unknown"; } // Temiz null kontrolü (Java 8+) public String getUserName(User user) { return Optional.ofNullable(user) .map(User::getName) .orElse("Unknown"); } // Null Object pattern public class NullUser extends User { @Override public String getName() { return "Unknown"; } } public String getUserName(User user) { return user.getName(); // NullUser kullanıldığında her zaman "Unknown" döner }

14. Değişken isimlendirmede dikkat edilmesi gereken noktalar nelerdir?

Değişken isimlendirmede dikkat edilecek noktalar:

  • Anlamlı ve açıklayıcı isimler kullanın
  • Kısaltmalardan kaçının (yaygın kısaltmalar hariç)
  • Tutarlı bir isimlendirme stili kullanın (camelCase, snake_case vb.)
  • Sayısal ön ekler kullanmaktan kaçının
  • Boolean değişkenler için "is", "has" gibi ön ekler kullanın

Örnek:

java
// Kötü değişken isimlendirme int d; // elapsed time in days String s; // name boolean f; // is completed // İyi değişken isimlendirme int elapsedTimeInDays; String name; boolean isCompleted;

15. Magic number'lar neden kötüdür ve nasıl önlenir?

Magic number'lar, kodda doğrudan kullanılan sayısal değerlerdir. Kötüdürler çünkü:

  • Kodun okunabilirliğini azaltır
  • Değişiklik yapılması gerektiğinde zorluklara neden olur
    • Kodun anlamını gizler

    Magic number'ları önlemek için:

    • Anlamlı isimlerle sabitler tanımlayın
    • Enum'ları kullanın

    Örnek:

    java
    // Magic number kullanımı if (employee.getDaysWorked() > 260) { employee.giveBonus(); } // Sabit kullanımı public static final int WORKING_DAYS_IN_YEAR = 260; if (employee.getDaysWorked() > WORKING_DAYS_IN_YEAR) { employee.giveBonus(); } // Enum kullanımı public enum Month { JANUARY(31), FEBRUARY(28), MARCH(31), /* ... */; private final int days; Month(int days) { this.days = days; } public int getDays() { return days; } }

    16. Code smells nedir ve nasıl tespit edilir?

    Code smells, kodda potansiyel problemlere işaret eden belirtilerdir. Bazı yaygın code smells:

    • Duplicate code (Tekrarlanan kod)
    • Long method (Uzun metot)
    • Large class (Büyük sınıf)
    • Long parameter list (Uzun parametre listesi)
    • Divergent change (Farklı nedenlerle değişen sınıf)
    • Shotgun surgery (Bir değişiklik için birçok yerde düzenleme yapma)
    • Feature envy (Başka sınıfların verilerine aşırı ilgi)

    Code smells'ı tespit etmek için:

    • Kod incelemeleri yapın
    • Statik kod analiz araçları kullanın
    • Düzenli refactoring yapın

    Örnek (Long Method):

    java
    // Code smell: Long Method public void processOrder(Order order) { // 100+ satır kod... } // Refactored public void processOrder(Order order) { validateOrder(order); calculateTotalPrice(order); applyDiscounts(order); updateInventory(order); notifyCustomer(order); } private void validateOrder(Order order) { /* ... */ } private void calculateTotalPrice(Order order) { /* ... */ } private void applyDiscounts(Order order) { /* ... */ } private void updateInventory(Order order) { /* ... */ } private void notifyCustomer(Order order) { /* ... */ }

    17. Immutability nedir ve neden önemlidir?

    Immutability, bir nesnenin oluşturulduktan sonra değiştirilemez olması anlamına gelir. Önemlidir çünkü:

    • Thread-safe'dir
    • Yan etkileri azaltır
    • Kodun anlaşılmasını kolaylaştırır
    • Hata olasılığını azaltır

    Örnek:

    java
    // Mutable class public class MutablePerson { private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } } // Immutable class public final class ImmutablePerson { private final String name; private final int age; public ImmutablePerson(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }

    18. Design patterns nedir ve neden önemlidir?

    Design patterns, yazılım geliştirmede sık karşılaşılan problemlere genel çözümler sunan yeniden kullanılabilir tasarım şablonlarıdır. Önemlidirler çünkü:

    • Kanıtlanmış çözümler sunarlar
    • Kod tekrarını azaltırlar
    • Kodun bakımını kolaylaştırırlar
    • Geliştiriciler arasında ortak bir dil oluştururlar

    Örnek (Singleton pattern):

    java
    public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }

    19. Composition over inheritance prensibi nedir?

    Bu prensip, miras alma (inheritance) yerine kompozisyonu (composition) tercih etmeyi önerir. Çünkü:

    • Daha esnek bir tasarım sağlar
    • Sıkı bağlılığı (tight coupling) azaltır
    • Kodun yeniden kullanılabilirliğini artırır

    Örnek:

    java
    // Inheritance public class Car extends Vehicle { // Car specific methods } // Composition public class Car { private Engine engine; private Wheels wheels; public Car(Engine engine, Wheels wheels) { this.engine = engine; this.wheels = wheels; } // Car specific methods }

    20. Test Driven Development (TDD) nedir ve nasıl uygulanır?

    TDD, önce testlerin yazıldığı, sonra bu testleri geçecek kodun geliştirildiği bir yazılım geliştirme yaklaşımıdır. TDD döngüsü:

    1. Başarısız bir test yaz
    2. Testi geçecek minimum kodu yaz
    3. Kodu refactor et

    Örnek:

    java
    // 1. Başarısız test @Test public void testAddition() { Calculator calc = new Calculator(); assertEquals(5, calc.add(2, 3)); } // 2. Testi geçecek kod public class Calculator { public int add(int a, int b) { return a + b; } } // 3. Refactoring (gerekirse)

    21. KISS (Keep It Simple, Stupid) prensibi nedir?

    KISS prensibi, tasarımların ve kodların mümkün olduğunca basit tutulması gerektiğini savunur. Karmaşık çözümler yerine basit ve anlaşılır çözümler tercih edilmelidir.

    Örnek:

    java
    // Karmaşık (KISS'e uygun değil) public boolean isEven(int number) { return number % 2 == 0 ? true : false; } // Basit (KISS'e uygun) public boolean isEven(int number) { return number % 2 == 0; }

    22. YAGNI (You Ain't Gonna Need It) prensibi nedir?

    YAGNI, geliştiricilerin sadece mevcut gereksinimleri karşılayan özellikleri uygulaması gerektiğini, gelecekte ihtiyaç duyulabilecek özellikleri önceden eklememesi gerektiğini savunur.

    Örnek:

    java
    // YAGNI'ye uygun olmayan kod public class User { private String name; private String email; private String address; // Şu an gerekli değil private String phoneNumber; // Şu an gerekli değil // Getters and setters... } // YAGNI'ye uygun kod public class User { private String name; private String email; // Getters and setters... }

    23. Code review'ın önemi nedir ve nasıl etkili bir şekilde yapılır?

    Code review, başka geliştiricilerin kodu incelemesi ve geri bildirim vermesi sürecidir. Önemlidir çünkü:

    • Kod kalitesini artırır
    • Hataları erken tespit eder
    • Bilgi paylaşımını teşvik eder
    • Takım içi iletişimi güçlendirir

    Etkili code review için öneriler:

    • Küçük ve odaklanmış değişiklikler yapın
    • Yapıcı geri bildirim verin
    • Kod stili yerine mantığa odaklanın
    • Övgüyü de unutmayın

    24. Continuous Integration (CI) ve Continuous Deployment (CD) nedir?

    CI, geliştiricilerin kodlarını düzenli olarak bir ana depoya entegre etme pratiğidir. CD ise, bu entegre edilmiş kodun otomatik olarak üretim ortamına deploy edilmesidir.

    CI/CD'nin faydaları:

    • Hataların erken tespiti
    • Daha hızlı release döngüleri
    • Daha az manuel iş
    • Daha güvenilir deployments

    25. Nasıl etkili log yazılır?

    Etkili logging için öneriler:

    • Anlamlı log seviyeleri kullanın (DEBUG, INFO, WARN, ERROR)
    • Yapılandırılabilir logging kullanın
    • Hassas bilgileri loglamaktan kaçının
    • Bağlam bilgisi ekleyin
    • Performansı göz önünde bulundurun

    Örnek:

    java
    // Etkisiz logging logger.error("Hata oluştu"); // Etkili logging logger.error("Kullanıcı kimlik doğrulama hatası: Kullanıcı ID {}, IP {}", userId, ipAddress, exception);

    26. Defensive programming nedir?

    Defensive programming, kodun beklenmedik durumlarla başa çıkabilmesini sağlayan bir yaklaşımdır. Amaç, hataların oluşmasını önlemek ve oluşan hataların zararlı etkilerini minimize etmektir.

    Örnek:

    java
    public void processUserInput(String input) { if (input == null || input.trim().isEmpty()) { throw new IllegalArgumentException("Input cannot be null or empty"); } // Input işleme... }

    27. Code complexity nasıl ölçülür ve azaltılır?

    Code complexity, genellikle cyclomatic complexity ile ölçülür. Bu, kodun içindeki bağımsız yolların sayısını ölçer.

    Complexity'i azaltmak için:

    • Fonksiyonları küçük ve odaklanmış tutun
    • Derin iç içe geçmiş yapılardan kaçının
    • Erken return kullanın
    • Karmaşık koşulları method'lara ayırın

    Örnek:

    java
    // Yüksek complexity public void processOrder(Order order) { if (order != null) { if (order.isValid()) { if (order.getTotal() > 100) { applyDiscount(order); } else { processNormalOrder(order); } } else { rejectOrder(order); } } } // Düşük complexity public void processOrder(Order order) { if (order == null) { return; } if (!order.isValid()) { rejectOrder(order); return; } if (order.getTotal() > 100) { applyDiscount(order); } else { processNormalOrder(order); } }

    28. Code smells ve refactoring arasındaki ilişki nedir?

    Code smells, kodda potansiyel problemlere işaret eden belirtilerdir. Refactoring ise, kodun iç yapısını iyileştirme sürecidir. Code smells genellikle refactoring ihtiyacını gösterir.

    Örnek:

    java
    // Code smell: Duplicate code public void processUser(User user) { // Kullanıcı işleme kodu... } public void processAdmin(Admin admin) { // Aynı kullanıcı işleme kodu... } // Refactored public void processAccount(Account account) { // Genel hesap işleme kodu... }

    29. Clean code ve performans arasındaki denge nasıl sağlanır?

    Clean code ve performans arasında bir denge kurmak önemlidir. Genel yaklaşım:

    1. Önce clean code yazın
    2. Performans problemlerini ölçün
    3. Sadece gerekli yerlerde optimize edin

    Örnek:

    java
    // Clean ama potansiyel olarak yavaş public List<Integer> findEvenNumbers(List<Integer> numbers) { return numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); } // Daha hızlı ama daha az okunabilir public List<Integer> findEvenNumbers(List<Integer> numbers) { List<Integer> result = new ArrayList<>(); for (int n : numbers) { if (n % 2 == 0) { result.add(n); } } return result; }

    30. Clean Architecture nedir?

    Clean Architecture, yazılımı katmanlara ayırarak bağımlılıkları yöneten bir mimari yaklaşımdır. Ana prensipler:

    • Bağımlılık yönü içeriden dışarıya doğru olmalıdır
    • İç katmanlar dış katmanlardan haberdar olmamalıdır
    • İş mantığı framework'lerden bağımsız olmalıdır

    Örnek katmanlar:

    1. Entities (İş nesneleri)
    2. Use Cases (İş mantığı)
    3. Interface Adapters (Presenters, Controllers)
    4. Frameworks & Drivers (UI, Database, External Interfaces)

31. Separation of Concerns (SoC) prensibi nedir?

Separation of Concerns, bir programın farklı bölümlerinin farklı ve mümkün olduğunca bağımsız endişeleri (concerns) ele alması gerektiğini söyleyen bir tasarım prensibidir.

Örnek:

java
// SoC'ye uymayan kod public class UserService { public void registerUser(User user) { // Kullanıcı doğrulama if (!isValidUser(user)) { throw new IllegalArgumentException("Invalid user data"); } // Veritabanına kaydetme saveUserToDatabase(user); // E-posta gönderme sendWelcomeEmail(user); } } // SoC'ye uyan kod public class UserService { private UserValidator validator; private UserRepository repository; private EmailService emailService; public void registerUser(User user) { validator.validate(user); repository.save(user); emailService.sendWelcomeEmail(user); } }

32. Boy Scout Rule nedir?

Boy Scout Rule, "Kodu bulduğunuzdan daha temiz bırakın" der. Bu, her değişiklik yaptığınızda kodu biraz daha iyileştirmeniz gerektiği anlamına gelir.

Örnek:

java
// Orijinal kod public void processData(List<String> data) { for (int i = 0; i < data.size(); i++) { String item = data.get(i); // İşlem... } } // Boy Scout Rule uygulanmış kod public void processData(List<String> data) { for (String item : data) { processItem(item); } } private void processItem(String item) { // İşlem... }

33. Code coverage nedir ve neden önemlidir?

Code coverage, testler tarafından çalıştırılan kod miktarını ölçer. Önemlidir çünkü:

  • Test edilmemiş kod bölümlerini gösterir
  • Test kalitesini değerlendirmeye yardımcı olur
  • Gereksiz testleri belirlemeye yardımcı olur

Ancak, yüksek code coverage her zaman iyi test kalitesi anlamına gelmez.

34. Cohesion ve coupling nedir?

Cohesion, bir modülün veya sınıfın ne kadar iyi odaklandığını gösterir. Yüksek cohesion iyidir.

Coupling, modüller veya sınıflar arasındaki bağımlılık derecesidir. Düşük coupling iyidir.

Örnek:

java
// Düşük cohesion, yüksek coupling public class UserManager { public void createUser() { /* ... */ } public void sendEmail() { /* ... */ } public void generateReport() { /* ... */ } } // Yüksek cohesion, düşük coupling public class UserManager { private EmailService emailService; private ReportGenerator reportGenerator; public void createUser() { /* ... */ } } public class EmailService { public void sendEmail() { /* ... */ } } public class ReportGenerator { public void generateReport() { /* ... */ } }

35. Law of Demeter (LoD) nedir?

Law of Demeter, bir nesnenin yalnızca yakın arkadaşlarıyla konuşması gerektiğini söyleyen bir tasarım prensibidir. "Yabancılarla konuşma, sadece yakın arkadaşlarınla konuş" olarak da bilinir.

Örnek:

java
// LoD'yi ihlal eden kod public class Car { private Engine engine; public void start() { engine.getFuelInjector().inject(); engine.getIgnition().fire(); } } // LoD'ye uyan kod public class Car { private Engine engine; public void start() { engine.start(); } } public class Engine { private FuelInjector fuelInjector; private Ignition ignition; public void start() { fuelInjector.inject(); ignition.fire(); } }

36. Tell, Don't Ask prensibi nedir?

Tell, Don't Ask prensibi, nesnelere ne yapmaları gerektiğini söylememiz gerektiğini, onların iç durumlarını sorgulayıp bu bilgiye göre hareket etmememiz gerektiğini belirtir.

Örnek:

java
// Tell, Don't Ask'i ihlal eden kod if (user.isAdmin()) { user.grantAdminAccess(); } // Tell, Don't Ask'e uyan kod user.grantAccessBasedOnRole();

37. CQRS (Command Query Responsibility Segregation) nedir?

CQRS, bir sistemin komut (yazma) ve sorgu (okuma) işlemlerini ayırma prensibidir. Bu, ölçeklenebilirlik ve performans avantajları sağlayabilir.

Örnek:

java
// CQRS öncesi public class UserService { public User getUser(int id) { /* ... */ } public void updateUser(User user) { /* ... */ } } // CQRS sonrası public class UserQueryService { public UserDTO getUser(int id) { /* ... */ } } public class UserCommandService { public void updateUser(UpdateUserCommand command) { /* ... */ } }

38. Fail-fast prensibi nedir?

Fail-fast prensibi, hataların mümkün olduğunca erken tespit edilmesi ve raporlanması gerektiğini söyler. Bu, hataların daha kolay tespit edilmesini ve düzeltilmesini sağlar.

Örnek:

java
// Fail-fast olmayan kod public void processOrder(Order order) { // Uzun işlem... if (order == null) { return; // Hata çok geç fark edildi } // Daha fazla işlem... } // Fail-fast kod public void processOrder(Order order) { Objects.requireNonNull(order, "Order cannot be null"); // İşlem devam eder... }

39. Design by Contract nedir?

Design by Contract, metodların ve sınıfların davranışlarını önceden tanımlanmış sözleşmelerle (preconditions, postconditions, invariants) belirtme yaklaşımıdır.

Örnek:

java
/** * @param dividend must be non-negative * @param divisor must be positive * @return the quotient of the division * @throws IllegalArgumentException if preconditions are not met */ public int divide(int dividend, int divisor) { if (dividend < 0 || divisor <= 0) { throw new IllegalArgumentException("Preconditions not met"); } int result = dividend / divisor; assert result >= 0 : "Postcondition: result should be non-negative"; return result; }

40. Feature Flags (Feature Toggles) nedir?

Feature Flags, kodun belirli bölümlerini çalışma zamanında etkinleştirip devre dışı bırakmayı sağlayan bir tekniktir. Bu, sürekli entegrasyonu ve dağıtımı kolaylaştırır.

Örnek:

java
public class FeatureManager { private Map<String, Boolean> features = new HashMap<>(); public void enableFeature(String featureName) { features.put(featureName, true); } public boolean isFeatureEnabled(String featureName) { return features.getOrDefault(featureName, false); } } public class UserService { private FeatureManager featureManager; public void processUser(User user) { if (featureManager.isFeatureEnabled("newUserProcessing")) { // Yeni işlem... } else { // Eski işlem... } } }

41. Semantic versioning nedir?

Semantic versioning (SemVer), yazılım sürümlerini MAJOR.MINOR.PATCH formatında numaralandırma sistemidir:

  • MAJOR: Geriye dönük uyumsuz API değişiklikleri
  • MINOR: Geriye dönük uyumlu yeni işlevsellik
  • PATCH: Geriye dönük uyumlu hata düzeltmeleri

Örnek: 2.4.1

42. Technical debt nedir ve nasıl yönetilir?

Technical debt, hızlı geliştirme veya optimal olmayan çözümler nedeniyle oluşan ve gelecekte ele alınması gereken kod problemleridir.

Yönetim stratejileri:

  • Düzenli refactoring
  • Boy Scout Rule uygulanması
  • Technical debt'in görünür kılınması (örn. TODO yorumları)
  • Debt geri ödeme zamanının planlanması

43. Premature optimization nedir ve neden kaçınılmalıdır?

Premature optimization, henüz gerekli olmadan kodu optimize etme çabasıdır. Kaçınılmalıdır çünkü:

  • Kod karmaşıklığını artırabilir
  • Gerçek performans darboğazlarından uzaklaştırabilir
  • Geliştirme süresini uzatabilir

Donald Knuth'un sözü: "Premature optimization is the root of all evil."

44. Dependency Injection nedir?

Dependency Injection, bir nesnenin bağımlılıklarının dışarıdan sağlanması prensibidir. Bu, kodun daha modüler ve test edilebilir olmasını sağlar.

Örnek:

java
// Dependency Injection olmadan public class UserService { private UserRepository repository = new UserRepository(); public User getUser(int id) { return repository.findById(id); } } // Dependency Injection ile public class UserService { private UserRepository repository; public UserService(UserRepository repository) { this.repository = repository; } public User getUser(int id) { return repository.findById(id); } }

45. Inversion of Control (IoC) nedir?

Inversion of Control, bir programın akışının kontrolünü bir framework'e devretme prensibidir. Dependency Injection, IoC'nin bir formudur.

Örnek: Spring Framework'ün bean yönetimi

java
@Component public class UserService { @Autowired private UserRepository repository; // ... }

46. Domain-Driven Design (DDD) nedir?

Domain-Driven Design, karmaşık yazılım projelerini domain modelini merkeze alarak tasarlama yaklaşımıdır. Ana konseptleri:

  • Ubiquitous Language
  • Bounded Contexts
  • Aggregates
  • Entities
  • Value Objects

Örnek:

java
public class Order { private OrderId id; private Customer customer; private List<OrderItem> items; private OrderStatus status; public void addItem(Product product, int quantity) { // ... } public void place() { // ... } }

47. Microservices mimarisi nedir?

Microservices, bir uygulamayı küçük, bağımsız ve birbirleriyle iletişim kurabilen servislere bölen bir mimari yaklaşımdır.

Avantajları:

  • Ölçeklenebilirlik
  • Teknoloji çeşitliliği
  • Hızlı dağıtım
  • İzolasyon

Dezavantajları:

  • Karmaşıklık
  • Ağ gecikmeleri
  • Veri tutarlılığı zorlukları

48. Event-driven architecture nedir?

Event-driven architecture, sistemlerin olayları (events) üreterek, tespit ederek ve tüketerek iletişim kurduğu bir mimari stildir.

Örnek:

java
public interface EventListener { void onEvent(Event event); } public class OrderCreatedEvent implements Event { private Order order; // ... } public class InventoryService implements EventListener { @Override public void onEvent(Event event) { if (event instanceof OrderCreatedEvent) { updateInventory((OrderCreatedEvent) event); } } }

49. Continuous Refactoring nedir?

Continuous Refactoring, kodu sürekli olarak iyileştirme ve yeniden düzenleme pratiğidir. Amaç, teknik borcu azaltmak ve kodun kalitesini sürekli olarak artırmaktır.

Stratejiler:

  • Boy Scout Rule uygulanması
  • Küçük, sık refactoring'ler
  • Automated refactoring araçlarının kullanımı
  • Code reviews sırasında refactoring önerilerinin yapılması

50. Behavior-Driven Development (BDD) nedir?

Behavior-Driven Development, yazılımın davranışını doğal dilde tanımlayan ve bu tanımları otomatik testlere dönüştüren bir geliştirme yaklaşımıdır.

Örnek (Cucumber ile):

gherkin
Feature: User Registration Scenario: Successful registration Given I am on the registration page When I enter valid user information And I submit the registration form Then I should see a success message And I should receive a confirmation email

Bu sorular ve cevaplar, clean code prensiplerini, yazılım tasarımı ve mimari konularını kapsamlı bir şekilde ele almaktadır. Her bir konu, junior geliştiricilerin anlaması ve uygulaması gereken önemli konseptleri içermektedir.

Please Select Embedded Mode To Show The Comment System.*

Daha yeni Daha eski

نموذج الاتصال