Mülakat soruları
Yazılım mühendisi mülakat soruları
Kodlama kalıpları, veri yapıları, algoritmalar, system design, debug, test, canlı ortam muhakemesi ve davranışsal iş birliği konularında yazılım mühendisi mülakat sorularıyla pratik yapın. Kapsamlı bir hazırlık için bu odaklı soru listesini şu rehberle birlikte kullanın: Yazılım mühendisi mülakat rehberi.
19 soru
6 kategori
Yazılım mühendisi
Son güncelleme: Mayıs 2026
Diziler, string'ler ve hash map'ler
Diziler, string'ler ve hash map'ler pek çok teknik ön elemenin temelini oluşturur. Mülakatçılar bu konularla indeksleme disiplininizi, frekans sayımını, iki işaretçi (two pointers) ve kayan pencere (sliding window) tekniklerini ve uygulamadaki titizliğinizi ölçer.
Çerçeve: Tümleyeni arama
Kaba kuvvet yaklaşımı tüm çiftleri tek tek kontrol eder; bu da O(n^2) sürer. Daha iyi bir yaklaşım olarak değerden indekse giden bir hash map kullanırım. Diziyi tararken her x sayısı için ihtiyacım olan değer target - x olur. Bu tümleyen map'te zaten varsa mevcut indeksi ve saklanan indeksi döndürürüm. Yoksa x'i indeksiyle birlikte kaydedip devam ederim. Doğruluğun temelindeki fikir şu: i indeksini işlerken map'te tam olarak önceki indekslerdeki değerler bulunur. Dolayısıyla i'de biten geçerli bir çift varsa onu anında bulurum. Yalnızca önceki elemanlarla eşleştirdiğim için aynı elemanı iki kez kullanma riski de ortadan kalkar. Her değer bir kez eklenip bir kez arandığı için zaman karmaşıklığı O(n). Map nedeniyle alan karmaşıklığı da O(n). Uç durumlar arasında tekrar eden değerler, negatif sayılar, sıfır ve soru buna izin veriyorsa hiç geçerli çift olmaması var.
Olası takip soruları
Dizi sıralı olsaydı ne değişirdi?
Tek bir çift yerine tüm çiftleri bulmanız gerekseydi ne yapardınız?
Aynı elemanı iki kez döndürmekten nasıl kaçınırsınız?
Çerçeve: Son görülme indeksiyle kayan pencere
İçinde her zaman yalnızca benzersiz karakterler bulunan bir kayan pencere kullanırım. Bir left işaretçisi ve her karakteri en son görüldüğü indekse eşleyen bir map tutarım. right ile string boyunca ilerlerim. Mevcut karakter şu anki pencerenin içinde daha önce görülmüşse left'i o karakterin önceki indeksinin bir sonrasına taşırım. Ardından karakterin indeksini güncelleyip maksimum pencere uzunluğunu kaydederim. Burada kritik ayrıntı, left'in yalnızca ileri gitmesi gerektiği. Bir karakter mevcut pencereden önce görülmüşse pencereyi daraltmamalı. Güncellemenin left = max(left, lastSeen[char] + 1) olmasının nedeni bu. Her karakter bir kez işlendiği ve left işaretçisi yalnızca ileri gittiği için zaman karmaşıklığı O(n). Alan karmaşıklığı O(k); burada k karakter kümesinin büyüklüğü. Uç durumlar arasında boş string, tamamı benzersiz karakterler, tamamı tekrar eden karakterler ve kullanılan dil karakterleri baytlardan farklı ele alıyorsa Unicode var.
Olası takip soruları
Girdi Unicode karakterler içeriyorsa ne olur?
Alt dizenin kendisini nasıl döndürürdünüz?
Her karakter en fazla iki kez geçebiliyorsa ne değişir?
Çerçeve: Kanonik anahtar
Anagramlar aynı karakter bileşimine sahiptir. Her kelime için kanonik bir anahtar oluşturur ve kelimeleri bir hash map'te bu anahtara göre gruplarım. En doğrudan anahtar, kelimenin sıralanmış karakterleridir. Örneğin “eat”, “tea” ve “ate” kelimelerinin hepsi “aet” anahtarına eşlenir. String'ler kısaysa her kelimeyi sıralamak basit ve güvenilirdir. Alfabe küçük harfli İngilizce harflerle sınırlıysa ve string'ler uzunsa 26 elemanlı bir frekans tuple'ı daha hızlı olabilir; çünkü kelime başına O(k log k) sıralama maliyetini ortadan kaldırır. Sıralamayla zaman karmaşıklığı O(n * k log k) olur; burada n string sayısı, k ise ortalama string uzunluğudur. Sabit alfabeyle sayım yapıldığında bu O(n * k) seviyesine inebilir. Çıktı ve anahtarlar için alan karmaşıklığı O(n * k). Uç durumlar arasında boş string'ler, tekrarlar, büyük/küçük harf kuralları ve İngilizce dışı karakterler var.
Olası takip soruları
Sıralama yerine frekans anahtarını ne zaman kullanırsınız?
Büyük/küçük harfe duyarsız gruplamayı nasıl ele alırdınız?
Karakter kümesi sabit değilse ne olur?
Bağlı listeler, ağaçlar ve graflar
İşaretçi ve gezinme (traversal) problemleri, durumu dikkatle yönetip yönetemediğinizi ölçer. Zor olan genellikle sözdizimi değildir; asıl zorluk her işaretçinin, kuyruğun, yığının veya ziyaret edilenler kümesinin neyi temsil ettiğini tanımlamaktır.
Çerçeve: Üç işaretçi: previous, current, next
Üç işaretçi kullanırım. previous null olarak, current ise head'den başlar. Her düğümde önce next = current.next değerini saklar, current.next'i previous'a yönlendirir, sonra previous'ı current'a, current'ı da next'e taşırım. current null olduğunda yeni head previous olur. Değişmez şu: previous ters çevrilmiş kısmı, current ise henüz ters çevrilmemiş ilk düğümü gösterir. current.next'i değiştirmeden önce next'i saklamak şart; aksi hâlde listenin geri kalanı kaybolur. Zaman karmaşıklığı O(n), alan karmaşıklığı O(1). Uç durumlar arasında boş liste, tek düğümlü liste ve orijinal head'in, next değeri null olan tail'e dönüştüğünden emin olmak var.
Olası takip soruları
Yalnızca m ile n konumları arasındaki alt listeyi nasıl ters çevirirdiniz?
Bir listeyi özyinelemeli olarak nasıl ters çevirirdiniz?
Ters çevirmeden önce döngüyü nasıl tespit edersiniz?
Çerçeve: Aralık kısıtları
Sık yapılan bir hata, yalnızca her düğümün sol çocuğundan büyük, sağ çocuğundan küçük olup olmadığını kontrol etmektir. Bu yeterli değildir; çünkü alt ağacın tamamı atalardan gelen kısıtları da sağlamalıdır. Alt ve üst sınırlarla DFS kullanırım. Her düğüm için lower < node.value < upper koşulunu doğrularım. Sol çocuk aynı alt sınırı, üst sınır olarak da mevcut değeri alır. Sağ çocuk ise alt sınır olarak mevcut değeri, üst sınır olarak da aynı üst sınırı alır. Herhangi bir düğüm kendi aralığını ihlal ederse false döndürürüm. Her düğüm bir kez ziyaret edildiği için zaman karmaşıklığı O(n). Özyineleme derinliği nedeniyle alan karmaşıklığı O(h); burada h ağacın yüksekliği. Uç durumlar arasında tekrar eden değerler, tam sayı min/max sınırları, boş ağaç ve dengesiz (skewed) ağaçlar var. Tekrar eden değerlere izin verilip verilmediğini, veriliyorsa hangi tarafta yer alacaklarını netleştiririm.
Olası takip soruları
Bunu inorder gezinmeyle nasıl çözerdiniz?
Tekrar eden değerlere izin veriliyorsa ne olur?
En kötü durumda özyineleme derinliği nedir?
Çerçeve: Mesafe katmanlarıyla genişlik öncelikli arama
Her açık hücreyi bir graf düğümü, yukarı, aşağı, sola veya sağa yapılan her hareketi de eşit ağırlıklı bir kenar olarak modellerim. Her hareketin maliyeti aynı olduğu için en kısa yolu BFS verir. Başlangıç hücresini 0 mesafesiyle kuyruğa ekler ve ziyaret edildi olarak işaretlerim. Kuyruktan çıkan her hücre için sınırlar içinde kalan, engel olmayan ve henüz ziyaret edilmemiş geçerli komşuları incelerim. Hedefe ilk ulaştığım anda mesafe minimumdur. Doğruluk, BFS'nin düğümleri artan mesafe sırasıyla işlemesinden gelir. Ağırlıksız bir grafta bir hücre bir kez ziyaret edildiyse ona daha sonra ulaşmak daha kısa bir yol üretemez. Her hücre en fazla bir kez ziyaret edildiği için zaman karmaşıklığı O(satır * sütun). Kuyruk ve ziyaret edilenler kümesi için alan karmaşıklığı da O(satır * sütun). Uç durumlar arasında başlangıç veya bitiş hücresinin kapalı olması, başlangıcın hedefle aynı olması, hiç yol olmaması ve çapraz hareketlere izin verilip verilmediği var.
Olası takip soruları
Çapraz harekete izin verilirse ne değişir?
Engellerden geçmek imkânsız değil de ek maliyetliyse ne olur?
Asıl yolu nasıl yeniden oluşturursunuz?
Çerçeve: Orijinal düğümü klon düğüme eşleyen ziyaret map'i
Her orijinal düğümü klonuna eşleyen bir hash map kullanırım. DFS veya BFS sırasında bir orijinal düğümü ziyaret ettiğimde, klonu henüz yoksa oluştururum. Ardından her komşuyu özyinelemeli ya da iteratif olarak klonlar ve klonlanmış komşuyu klon düğümün komşuluk listesine eklerim. Ziyaret map'i iki sorunu çözer: Döngüsel graflarda sonsuz döngüleri engeller ve ortak referansları korur; böylece klonlanmış graf orijinal grafla aynı topolojiye sahip olur. Zaman karmaşıklığı O(V + E); burada V düğüm, E kenar sayısı. Çıktı grafı hariç, map ve gezinme yığını ya da kuyruğu için alan karmaşıklığı O(V). Uç durumlar arasında null girdi, kendine dönen kenarlar (self-loop), soru yalnızca bir başlangıç düğümünden klonlama bekliyorsa bağlantısız graflar ve tekrar eden komşu kayıtları var.
Olası takip soruları
Bağlantısız bir grafı nasıl ele alırdınız?
Yönlü bir graf için ne değişir?
Sonsuz özyinelemeden nasıl kaçınırsınız?
Dinamik programlama ve backtracking
Dinamik programlama ve backtracking soruları durum tanımlama becerinizi ölçer. En güçlü yanıtlar her durumdaki kararı, yineleme bağıntısını (recurrence) ve örtüşen alt problemlerin ya da budamanın neden geçerli olduğunu açıklar.
Çerçeve: Tutar üzerinden bottom-up DP
dp[a] değerini, a tutarını oluşturmak için gereken minimum madeni para sayısı olarak tanımlarım. dp[0] = 0 ile başlatır, diğer tüm değerleri sonsuz yaparım. 1'den hedef tutara (target) kadar her tutar için tüm madeni paraları denerim. a - coin negatif değilse dp[a] = min(dp[a], dp[a - coin] + 1) olur. Sonunda dp[target] hâlâ sonsuzsa -1 döndürürüm. Yineleme bağıntısı işe yarar; çünkü optimal bir çözümdeki son madeni para mutlaka verilen değerlerden biridir. Bu son paranın değeri c ise kalan tutar target - c olur ve o da optimal şekilde çözülmelidir. Zaman karmaşıklığı O(tutar * madeni para sayısı), alan karmaşıklığı O(tutar). Uç durumlar arasında 0 tutarı, oluşturulamayan tutarlar, 1 değerinde madeni para, tekrar eden değerler ve büyük hedef tutarlar var.
Olası takip soruları
Kullanılan madeni paraların kendisini nasıl döndürürdünüz?
Her madeni para yalnızca bir kez kullanılabiliyorsa ne değişir?
Bunun yerine kombinasyon sayısını nasıl hesaplardınız?
Çerçeve: Bitiş konumuna göre DP, ardından ikili aramayla optimizasyon
Net bir DP çözümünde dp[i], i indeksinde biten en uzun artan alt dizinin uzunluğu olarak tanımlanır. Her i için önceki tüm j'leri kontrol ederim. nums[j] < nums[i] ise nums[i], j'de biten alt diziyi uzatabilir; dolayısıyla dp[i] = max(dp[i], dp[j] + 1). Yanıt max(dp) olur. Bu yaklaşım O(n^2) zaman ve O(n) alan gerektirir. Optimize edilmiş O(n log n) yaklaşımda tails adlı bir dizi tutarım; tails[length - 1], o uzunluktaki artan bir alt dizinin alabileceği en küçük bitiş değeridir. Her sayı için ikili aramayla ondan büyük veya ona eşit ilk tail değerini bulur ve yerine bu sayıyı koyarım. tails dizisinin uzunluğu LIS uzunluğunu verir. Mülakatta süre kısıtlıysa önce O(n^2) DP çözümünü sunup ardından optimize edilmiş versiyonu tartışmak makul bir yaklaşım. Uç durumlar arasında tekrar eden değerler, azalan diziler, boş girdi ve alt dizinin kesin olarak artan olması gerekip gerekmediği var.
Olası takip soruları
Alt diziyi nasıl yeniden oluşturursunuz?
Azalmayan alt diziler için ne değişir?
Bir tail değerini değiştirmek neden yanıtı kaybettirmez?
Çerçeve: Yalnızca geçerli önekler oluşturma
İki sayaçla backtracking kullanırım: kullanılan açma (open) ve kapama (close) parantezi sayısı. Her adımda open < n ise açma parantezi, close < open ise kapama parantezi ekleyebilirim. İkinci koşul her önekin geçerli kalmasını sağlar; böylece sonradan filtrelenmesi gereken geçersiz string'leri hiç üretmem. Mevcut string'in uzunluğu 2n'e ulaştığında onu sonuca eklerim. Bu yöntem yalnızca geçerli önekleri keşfeder ve imkânsız durumları erkenden budar. Geçerli çıktıların sayısı n'inci Catalan sayısıdır; dolayısıyla çalışma süresini çıktı boyutu belirler. Alan karmaşıklığı O(n) özyineleme derinliğini ve çıktıyı kapsar. Uç durumlar arasında, sorunun tanımına bağlı olarak n = 0 veya n = 1 var.
Olası takip soruları
Neden yalnızca close < open olduğunda kapatabiliriz?
Birden fazla parantez türünü nasıl ele alırdınız?
Sonuçları sözlük sırasıyla (lexicographic order) üretebilir misiniz?
System design mülakatları
System design mülakatları mühendislik olgunluğunu değerlendirir. Orta seviye pozisyonlarda amaç temel mimariyi ve veri akışını ortaya koymaktır. Kıdemli pozisyonlarda ise çıta trade-off'lar, darboğazlar, güvenilirlik, gözlemlenebilirlik ve operasyonel sahiplenmedir.
Çerçeve: Gereksinimler → API → ID üretimi → depolama → yönlendirme yolu → ölçek
Gereksinimler: Kullanıcılar uzun bir URL gönderip kısa bir URL alır. Biri bu kısa adresi ziyaret ettiğinde hızlıca yönlendirilmelidir. İsteğe bağlı özellikler arasında özel takma adlar (alias), son kullanma tarihi, analitik, spam tespiti ve kullanıcı hesapları yer alır. Temel API'ler: createShortUrl(longUrl, optionalAlias, expiration) ve redirect(shortCode). Veri modeli: shortCode, longUrl, userId, createdAt, expiresAt, status ve gerekiyorsa analitik meta verileri. ID üretimi için seçenekler arasında base62 ile kodlanmış auto-increment ID'ler, çakışma kontrolüyle rastgele base62 kodlar veya dağıtık ID üretimi var. Auto-increment basittir ama gizlenmezse hacmi açığa çıkarır. Rastgele ID'leri dağıtmak kolaydır ama çakışmaların ele alınması gerekir. Orta ölçekte, veritabanında benzersizlik kısıtıyla rastgele base62 kabul edilebilir bir çözümdür. En önemli kısım okuma yolu. Yönlendirme hızlı olmalı: shortCode önbellekten okunur, bulunamazsa veritabanına gidilir, son kullanma tarihi/durum doğrulanır ve ardından HTTP 301 veya 302 döndürülür. Analitik veya hedef adresin değişebilmesi önemliyse 302, tarayıcıda daha güçlü önbelleğe alma sağlayan kalıcı yönlendirmeler için 301 kullanırım. Ölçek: Sık erişilen kısa kodları Redis'te veya edge cache'te tutarım, gerekirse veriyi shortCode'a göre shard'lara bölerim, analitik verilerini bir kuyruk üzerinden asenkron olarak kaydederim, oluşturma işlemine rate limit uygular ve spam/zararlı yazılım kontrolleri çalıştırırım. Yönlendirme gecikmesini, cache hit oranını, hata oranını, kötüye kullanım bildirimlerini ve veritabanı doygunluğunu izlerim.
Olası takip soruları
Benzersiz kısa kodları nasıl üretirdiniz?
301 mi yoksa 302 yönlendirme mi kullanırdınız?
Yönlendirmeleri yavaşlatmadan analitiği nasıl desteklerdiniz?
Çerçeve: Kullanıcılar → gönderiler → fanout → sıralama → okumalar → tutarlılık
Önce akış türünü netleştiririm: Sosyal takip akışı mı, öneri akışı mı, yoksa karma bir akış mı? Kullanıcıların gönderi oluşturduğu ve takipçilerin bu gönderileri alaka düzeyine veya yeniliğe göre sıralanmış şekilde gördüğü bir takip akışı varsayıyorum. Temel nesneler: kullanıcılar, takip ilişkileri (follow edges), gönderiler, medya, akış öğeleri, beğeniler/yorumlar ve sıralama özellikleri (ranking features). API'ler arasında createPost, getFeed, followUser, unfollowUser ve interactWithPost var. Yaygın iki akış oluşturma modeli var. Fanout-on-write, bir gönderi oluşturulduğunda onu takipçilerin akış depolarına iter. Bu, okumaları hızlandırır ama çok takipçisi olan kullanıcılar için yazmaları pahalı hâle getirir. Fanout-on-read ise akışı istek geldiğinde, takip edilen kullanıcıların gönderilerini çekerek hesaplar. Bu, yazmaları ucuzlatır ama okumaları yavaşlatır. Yaygın olan hibrit bir yaklaşımdır: Normal kullanıcılar için fanout-on-write, ünlü hesaplar için fanout-on-read veya özel bir işleme. Mimari: Post servisi gönderileri yazar, graph servisi takip ilişkilerini saklar, feed servisi akış zaman çizelgelerini yönetir, ranking servisi aday gönderileri puanlar, önbellek sık erişilen akışları tutar, medya ise nesne depolamaya/CDN'e gider. Asenkron fanout ve sıralama güncellemeleri için kuyruklar kullanırım. Trade-off'lar: akış tazeliği ile sıralama kalitesi, takip değişikliklerinin tutarlılığı, ünlü kullanıcıların ele alınması, önbellek geçersizleştirme (cache invalidation), spam, gizlilik engellemeleri ve kuyruk hatalarından sonra eksik verilerin tamamlanması (backfill). Akış yükleme gecikmesini, tazeliği, fanout gecikmesini, etkileşimi, cache hit oranını, sıralama hatalarını ve kötüye kullanım bildirimlerini izlerim.
Olası takip soruları
Milyonlarca takipçisi olan kullanıcıları nasıl ele alırdınız?
Akış öğelerini nasıl sıralardınız?
Fanout kuyruğu gecikirse ne olur?
Çerçeve: Bağlantılar → mesaj akışı → kalıcılık → teslimat → güvenilirlik
Gereksinimler: Birebir ve grup mesajları, çevrimiçi teslimat, çevrimdışı teslimat, mesaj geçmişi, okundu bilgisi, yazıyor göstergesi ve push bildirimleri. Uçtan uca şifreleme, dosya ekleri ve çoklu cihaz eşzamanlamasının gerekip gerekmediğini netleştiririm. İstemciler bir gateway servisine WebSocket bağlantılarını açık tutar. Kullanıcı bir mesaj gönderdiğinde gateway gönderenin kimliğini doğrular, bir idempotency anahtarı atar veya alır, mesajı kalıcı depolamaya yazar, bir olay yayınlar ve mesajı çevrimiçi alıcılara aktif bağlantıları üzerinden iletir. Çevrimdışı kullanıcılar push bildirimi alır ve geçmişi daha sonra çekebilir. Veri modeli: sohbet, katılımcı, mesaj, teslimat durumu, okunma durumu ve cihaz/oturum. Depolamanın sohbete ve zamana göre verimli okumaları desteklemesi gerekir. Orta ölçekte ilişkisel bir veritabanı yeterli olabilir; daha büyük ölçekte dağıtık veri depoları kullanılır. Dosya ekleri mesaj veritabanına değil, nesne depolamaya gitmelidir. Güvenilirlik konuları: mükerrer gönderimler, sırasız teslimat, yeniden bağlanmalar, kaçırılan mesajlar, büyük gruplarda fanout ve çevrimiçi durum (presence) doğruluğu. Bunun için idempotency anahtarları, her sohbet için monoton artan sıra numaraları, onaylar (acknowledgement), yeniden deneme mantığı ve son görülen mesajdan itibaren eşzamanlama yapan API'ler kullanırım. Mesaj gönderme gecikmesini, teslimat başarı oranını, WebSocket bağlantı sayısını, yeniden bağlanma oranını, kuyruk gecikmesini, push bildirimi hatalarını ve depolama yazma hatalarını izlerim.
Olası takip soruları
Mesaj sıralamasını nasıl garanti ederdiniz?
Kullanıcı başına birden fazla cihazı nasıl desteklerdiniz?
Okundu bilgisi için neleri saklardınız?
Debug, test ve canlı ortam muhakemesi
Artık birçok yazılım mühendisliği mülakatında pratik debug, test veya canlı ortam senaryoları da yer alıyor. Bu sorular, kod yazabilen adayları yazılımı sorumlu bir şekilde işletebilen adaylardan ayırır.
Çerçeve: Doğrulayın → kapsamı belirleyin → son değişiklikler → bağımlılık kırılımı → etkiyi azaltın
Önce sinyali doğrularım. Gecikme artışının birden fazla izleme sisteminde görünüp görünmediğine ve p50, p95, p99'u mu yoksa yalnızca belirli bir endpoint'i mi etkilediğine bakarım. Kullanıcıların bunu fark edip etmediğini teyit ederim. Ardından sorunun kapsamını endpoint, bölge, availability zone, müşteri segmenti, sürüm, host, bağımlılık ve istek türüne göre daraltırım. Genel bir artış ortak bir bağımlılığa veya bir deploy'a işaret eder. Dar kapsamlı bir artış ise belirli bir route'u, sorguyu, müşteriyi veya altyapı bölgesini gösterir. Sonra son değişiklikleri incelerim: deploy'lar, konfigürasyon değişiklikleri, veritabanı migration'ları, trafik artışları, feature flag'ler, önbellek değişiklikleri veya alt servislerdeki olaylar. Trace'leri kullanarak gecikmeyi servis span'larına göre ayrıştırırım. Veritabanı sorgu süresine, cache hit oranına, kuyruk gecikmesine, CPU'ya, belleğe, garbage collection'a, thread pool'lara, connection pool'lara ve harici API'lere bakarım. Kullanıcılar etkileniyorsa etkiyi azaltmak, kök nedeni kusursuz biçimde bulmaktan önce gelir. Güvenliyse rollback yapar, bir feature flag'i kapatır, kapasiteyi artırır, yavaş bir bağımlılığı devre dışı bırakır veya cache TTL'yi uzatırım. Sistem toparlandıktan sonra kök nedeni, tespit eksikliğini ve önleme planını yazıya dökerim.
Olası takip soruları
Yalnızca p99 gecikmesi arttıysa ne yapardınız?
Rollback yapıp yapmamaya nasıl karar verirdiniz?
Hangi dashboard'ları görmek isterdiniz?
Çerçeve: Birim testleri → sınır durumları → geçersiz girdiler → değişmezler
Önce kuralları netleştiririm: indirim türleri, indirimlerin birleştirilip birleştirilemeyeceği, son kullanma tarihi, minimum sepet tutarı, kullanıcı uygunluğu, para birimi yuvarlaması ve vergilerin ya da kargonun dahil olup olmadığı. Birim testleri normal durumları, sınır durumlarını, geçersiz girdileri ve kurallar arasındaki etkileşimleri kapsamalı. Örnekler: indirimsiz durum, yüzdesel indirim, sabit tutarlı indirim, ara toplamdan büyük indirim, minimum tutarın tam olarak karşılanması, minimum tutarın hemen altında kalınması, süresi dolmuş indirim, uygun olmayan kullanıcı, izin veriliyorsa birden fazla indirim ve küsuratların yuvarlanması. Değişmezleri de test ederim: Nihai fiyat asla negatif olmamalı, indirim uygun ara toplamı aşmamalı, süresi dolmuş kampanyalar uygulanmamalı ve aynı hesaplama tekrarlandığında hep aynı sonucu vermeli. Bu fonksiyon ödemelere dokunuyorsa fiyatlandırma servisiyle entegrasyon testleri ve fatura çıktıları için snapshot testleri eklerim. Canlı ortam güvenliği için indirim kararlarını gerekçe kodlarıyla loglarım; böylece destek ve mühendislik ekipleri fiyatlandırma şikâyetlerini tahmin yürütmeden teşhis edebilir.
Olası takip soruları
Para birimi yuvarlamasını nasıl test ederdiniz?
Kampanya servisi çalışmıyorsa ne olmalı?
Hangi testler birim testlerine, hangileri entegrasyon testlerine aittir?
Çerçeve: Doğruluk → sürdürülebilirlik → risk → netlik
Kodu katman katman incelerim. Birincisi, amaçlanan problemi çözüyor ve doğruluğu koruyor mu? İkincisi, sürdürülebilir mi: Net isimler, makul sınırlar, gereksiz karmaşıklık olmaması ve tutarlı stil var mı? Üçüncüsü, risk nedir: Migration'lar, eşzamanlılık, güvenlik, performans, geriye dönük uyumluluk ve gözlemlenebilirlik açısından durum ne? Dördüncüsü, değişen davranış için testler yeterli mi? İyi bir code review üstünlük göstermekle ilgili değildir. Ekibin hızını korurken kodu iyileştirmelidir. Engelleyici sorunları önerilerden ayırırım. Bir doğruluk hatası, güvenlik açığı veya migration riski engelleyicidir. Bir isimlendirme tercihi ya da küçük bir refactor ise engelleyici olmayabilir. Eksik bağlamı da ararım: belirsiz ürün davranışı, test edilmemiş uç durumlar, sessizce başarısız olan akışlar, zayıf hata yönetimi ve riskli değişikliklerin etrafında metrik eksikliği.
Olası takip soruları
Code review'da fikir ayrılıklarını nasıl yönetirsiniz?
Bir yorumu engelleyici yapan nedir?
Ekibi yavaşlatmaktan nasıl kaçınırsınız?
Davranışsal ve iş birliği soruları
Mühendisler için davranışsal turlar sahiplenme, iş birliği, teknik muhakeme, belirsizlikle başa çıkma ve hatalardan ders çıkarma üzerine yoğunlaşır. Güçlü yanıtlar, teknik açıdan gerçekten önem taşıyan durumları anlatır.
Çerçeve: Bağlam → seçenekler → trade-off'lar → karar → sonuç
Gerçek trade-off'lar içeren bir karar seçin: şirket içinde geliştirmek mi satın almak mı, SQL mi NoSQL mi, monolit mi servis mi, hızlı bir yama mı daha derin bir refactor mı, ya da güçlü tutarlılık mı erişilebilirlik mi. Bağlam ve kısıtlarla başlayın, ardından değerlendirdiğiniz seçenekleri açıklayın. Güçlü bir yanıt trade-off'u net biçimde ortaya koyar. Örneğin: “A seçeneği bir haftada yayına çıkmamızı sağlıyordu ama operasyonel yükü artırıyordu. B seçeneği üç hafta sürdü ama bir ölçeklenme darboğazını ortadan kaldırdı.” Ardından kararı hangi verilerin yönlendirdiğini açıklayın: trafik, müşteri teslim tarihi, geçmiş olaylar, ekip kapasitesi veya uzun vadeli roadmap. Sonuçla ve öğrendiklerinizle bitirin. Karar kusursuz değilse neyi farklı yapacağınızı söyleyin. Mülakatçılar olgun muhakemeye, her kararın apaçık olduğunu iddia etmekten daha çok değer verir.
Olası takip soruları
Size kim itiraz etti?
Kararınızı ne değiştirebilirdi?
Kararın işe yarayıp yaramadığını nasıl ölçtünüz?
Çerçeve: Olay → etki → müdahale → kök neden → önleme
Mümkünse gerçek bir olay anlatın. Kullanıcıya etkisiyle başlayın: Ne bozuldu, kimler etkilendi ve ne kadar ciddiydi? Ardından müdahaledeki rolünüzü açıklayın: tespit, triyaj, rollback, etkiyi azaltma, iletişim veya kök neden analizi. En iyi yanıtlar sakin bir önceliklendirme ortaya koyar. Olay sırasında servisi yeniden ayağa kaldırmak, bir teoriyi kanıtlamaktan daha önemlidir. Log'ları, metrikleri, trace'leri, feature flag'leri, rollback'leri veya bağımlılık kontrollerini nasıl kullandığınızdan bahsedin. Etki azaltıldıktan sonra kök nedeni ve önleme adımlarını anlatın. İyi önlemler arasında daha iyi testler, daha güvenli rollout, izleme, alarm ayarlarının iyileştirilmesi, runbook'lar, circuit breaker'lar, backpressure veya migration güvenlik önlemleri olabilir. İnsanları suçlamaktan kaçının. Güçlü ekipler, aynı hatanın tekrarlanmasını zorlaştıracak şekilde sistemleri iyileştirir.
Olası takip soruları
Olay sırasında nasıl iletişim kurdunuz?
Hangi alarm bunu daha erken yakalayabilirdi?
Ekip sonrasında neleri değiştirdi?
Çerçeve: Ortak hedef → kısıtlar → seçenekler → trade-off'lar → karar
İşe kullanıcı hedefi ve iş hedefi üzerinde uzlaşarak başlarım. Fikir ayrılıklarının çoğu aslında mühendislik ile ürün arasındaki bir çatışma değil, farklı varsayımlardan kaynaklanır. Teknik kısıtı net bir şekilde açıklarım: karmaşıklık, güvenilirlik riski, zaman çizelgesi, sürdürülebilirlik, güvenlik veya performans. Ardından sadece hayır demek yerine seçenekler sunarım. Örneğin daha küçük bir MVP çıkarmak, geçici olarak manuel bir iş akışı kullanmak, özelliği bir feature flag arkasında tutmak, teknik işleri aşamalara bölmek ya da temel kullanıcı problemini yine çözen daha basit bir tasarım seçmek. Trade-off ciddiyse kararın şeffaf olması için seçenekleri, riskleri ve önerimi yazılı hâle getiririm. Amaç mühendisliğin kazanması değil. Amaç, ekibin her şeyi bilerek net bir karar vermesi.
Olası takip soruları
Ürün ekibi riskli seçenekte ısrar ederse ne yaparsınız?
Teknik borcu mühendis olmayanlara nasıl anlatırsınız?
Konuyu ne zaman bir üst seviyeye taşırsınız?
Bu yanıtlarla canlı pratik yapın
Interview Pilot, canlı mülakatlarda size gerçek zamanlı Copilot yanıt önerileri sunar; böylece bu sorular geldiğinde net yanıtlar verebilirsiniz.