Algoritmik Mülakat Soruları
- Soru: 1’den 100’e kadar sayılar için bir döngü oluşturun. Eğer sayı 3’e tam bölünüyorsa “Fizz”, 5’e tam bölünüyorsa “Buzz”, hem 3’e hem de 5’e tam bölünüyorsa “FizzBuzz” yazdırın
using System;
// Programın ana sınıfı
class Program
{
// Programın başlangıç noktası olan Main metodu
static void Main(string[] args)
{
// 1’den 100’e kadar olan sayılar için bir for döngüsü oluşturuyoruz.
for (int sayi = 1; sayi <= 100; sayi++)
{
// Sayının hem 3’e hem de 5’e tam bölünüp bölünmediğini kontrol ediyoruz.
// Bu en özel durum olduğu için ilk olarak kontrol edilmelidir.
if (sayi % 3 == 0 && sayi % 5 == 0)
{
// Koşul doğruysa konsola “FizzBuzz” yazdırıyoruz.
Console.WriteLine(“FizzBuzz”);
}
// Yukarıdaki koşul doğru değilse, sayının sadece 3’e tam bölünüp bölünmediğini kontrol ediyoruz.
else if (sayi % 3 == 0)
{
// Koşul doğruysa konsola “Fizz” yazdırıyoruz.
Console.WriteLine(“Fizz”);
}
// Yukarıdaki koşullar doğru değilse, sayının sadece 5’e tam bölünüp bölünmediğini kontrol ediyoruz.
else if (sayi % 5 == 0)
{
// Koşul doğruysa konsola “Buzz” yazdırıyoruz.
Console.WriteLine(“Buzz”);
}
// Yukarıdaki koşulların hiçbiri sağlanmıyorsa…
else
{
// Sayının kendisini konsola yazdırıyoruz.
Console.WriteLine(sayi);
}
}
}
}
-
Verilen bir sayının faktöriyelini hesaplayan bir fonksiyon yazın. (Örn: 5! = 120).
a) Döngüsel (İteratif) Yöntem
using System;
class Program
{
// Özyinelemeli olarak faktöriyel hesaplayan fonksiyon
public static long FaktoriyelRekursif(int sayi)
{
if (sayi < 0)
{
Console.WriteLine(“Negatif sayıların faktöriyeli hesaplanamaz.”);
return -1;
}
// Temel durum
if (sayi == 0)
{
return 1;
}
// Rekürsif adım
return sayi * FaktoriyelRekursif(sayi – 1);
}static void Main(string[] args)
{
int ornekSayi = 5;
long sonuc = FaktoriyelRekursif(ornekSayi);
if (sonuc != -1)
{
Console.WriteLine($”{ornekSayi}! = {sonuc}”); // 5! = 120
}
}
}b) Özyinelemeli (Rekürsif) Yöntem
using System;
class Program
{
// Özyinelemeli olarak faktöriyel hesaplayan fonksiyon
public static long FaktoriyelRekursif(int sayi)
{
if (sayi < 0)
{
Console.WriteLine(“Negatif sayıların faktöriyeli hesaplanamaz.”);
return -1;
}
// Temel durum
if (sayi == 0)
{
return 1;
}
// Rekürsif adım
return sayi * FaktoriyelRekursif(sayi – 1);
}static void Main(string[] args)
{
int ornekSayi = 5;
long sonuc = FaktoriyelRekursif(ornekSayi);
if (sonuc != -1)
{
Console.WriteLine($”{ornekSayi}! = {sonuc}”); // 5! = 120
}
}
}
- 1’den N’e kadar olan sayıları içeren bir diziden bir sayı çıkarılmıştır. Bu eksik sayıyı en verimli şekilde nasıl bulursunuz?
using System;
using System.Collections.Generic;class Program
{
public static int EnCokTekrarEdeniBul(int[] dizi)
{
// Dizi boş veya null ise hata fırlat
if (dizi == null || dizi.Length == 0)
{
throw new ArgumentException(“Dizi boş olamaz!”);
}// Sayıları ve tekrar sayılarını saklamak için bir sözlük oluştur
Dictionary<int, int> frekanslar = new Dictionary<int, int>();// Dizideki her sayıyı dolaş ve frekansını hesapla
foreach (int sayi in dizi)
{
if (frekanslar.ContainsKey(sayi))
{
frekanslar[sayi]++; // Sayı zaten sözlükte varsa sayacını artır
}
else
{
frekanslar[sayi] = 1; // Sayı sözlükte yoksa 1 değeriyle ekle
}
}// En çok tekrar eden sayıyı ve frekansını bul
int enCokTekrarEden = 0;
int maksimumFrekans = 0;foreach (var cift in frekanslar)
{
if (cift.Value > maksimumFrekans)
{
maksimumFrekans = cift.Value;
enCokTekrarEden = cift.Key;
}
}return enCokTekrarEden;
}static void Main(string[] args)
{
int[] sayiDizisi = { 1, 3, 5, 3, 2, 3, 4, 3, 5, 5, 5 };
int sonuc = EnCokTekrarEdeniBul(sayiDizisi);Console.WriteLine(“Sayı dizisi: [{0}]”, string.Join(“, “, sayiDizisi));
Console.WriteLine($”En çok tekrar eden sayı: {sonuc}”); // Çıktı: 3 (Eğer 5’ler daha fazla olsaydı 5 olurdu)// Karakter dizisi örneği
char[] karakterDizisi = { ‘a’, ‘b’, ‘c’, ‘a’, ‘b’, ‘b’, ‘d’ };
// Not: Bu fonksiyonu karakterler için kullanmak isterseniz,
// parametre ve değişken tiplerini ‘char’ olarak değiştirmeniz gerekir.
Console.WriteLine(“\nKarakter dizisi: [{0}]”, string.Join(“, “, karakterDizisi));
Console.WriteLine(“Karakterler için çözüm LINQ örneğinde gösterilmiştir.”);
}
}
Yöntem 2: LINQ Kullanarak Modern ve Kısa Çözüm
using System;
using System.Linq;class Program
{
static void Main(string[] args)
{
// — Sayı Dizisi Örneği —
int[] sayiDizisi = { 1, 4, 2, 5, 2, 6, 2, 7, 5, 2 };// LINQ sorgusu
var enCokTekrarEdenSayi = sayiDizisi
.GroupBy(sayi => sayi) // 1. Elemanları değerlerine göre grupla
.OrderByDescending(grup => grup.Count()) // 2. Grupları eleman sayılarına göre azalan sırada sırala
.First() // 3. Sıralamadaki ilk grubu al (en kalabalık olan)
.Key; // 4. O grubun anahtarını (elemanın kendisini) alConsole.WriteLine(“Sayı dizisi: [{0}]”, string.Join(“, “, sayiDizisi));
Console.WriteLine($”En çok tekrar eden sayı: {enCokTekrarEdenSayi}”); // Çıktı: 2Console.WriteLine(“\n” + new string(‘-‘, 20) + “\n”);
// — Karakter Dizisi Örneği —
string metin = “bugungunlerdenpazartesi”;
char[] karakterDizisi = metin.ToCharArray();var enCokTekrarEdenKarakter = karakterDizisi
.GroupBy(karakter => karakter)
.OrderByDescending(grup => grup.Count())
.First()
.Key;Console.WriteLine($”Metin: {metin}”);
Console.WriteLine($”En çok tekrar eden karakter: ‘{enCokTekrarEdenKarakter}'”); // Çıktı: ‘e’
}
}
- 1’den N’e kadar olan sayıları içeren bir diziden bir sayı çıkarılmıştır. Bu eksik sayıyı en verimli şekilde nasıl bulursunuz?
using System;
using System.Linq; // Dizi toplamı için .Sum() metodunu kullanmak isterseniz gereklidir.class Program
{
/// <summary>
/// 1’den N’e kadar olan sayıları içermesi gereken bir diziden
/// eksik olan tek sayıyı en verimli şekilde bulur.
/// </summary>
/// <param name=”dizi”>İçinde bir sayı eksik olan dizi.</param>
/// <returns>Eksik olan sayı.</returns>
public static int EksikSayiyiBul(int[] dizi)
{
// N, dizide olması gereken toplam eleman sayısıdır.
// Dizide şu an N-1 eleman olduğu için, N = dizi.Length + 1’dir.
int n = dizi.Length + 1;// 1. Olması gereken toplamı Gauss formülü ile hesapla.
// Olası ‘integer overflow’ (tam sayı taşması) riskine karşı
// büyük sayılarla çalışırken ‘long’ kullanmak daha güvenlidir.
long olmasiGerekenToplam = (long)n * (n + 1) / 2;// 2. Mevcut dizinin gerçek toplamını hesapla.
long mevcutToplam = 0;
foreach (int sayi in dizi)
{
mevcutToplam += sayi;
}// LINQ .Sum() metodu ile daha kısa bir yazım da mümkündür:
// long mevcutToplam = dizi.Sum(sayi => (long)sayi);// 3. İki toplam arasındaki fark, eksik olan sayıyı verir.
return (int)(olmasiGerekenToplam – mevcutToplam);
}static void Main(string[] args)
{
// Örnek: 1’den 10’a kadar sayılar olmalı, ama 7 eksik.
// N = 10
int[] ornekDizi = { 1, 2, 3, 4, 5, 6, 8, 9, 10 };int eksikSayi = EksikSayiyiBul(ornekDizi);
Console.WriteLine(“Dizi: [{0}]”, string.Join(“, “, ornekDizi));
Console.WriteLine($”Bu dizide eksik olan sayı: {eksikSayi}”);// Başka bir örnek: 1’den 5’e kadar, 1 eksik
int[] baskaDizi = { 5, 2, 3, 4 };
Console.WriteLine(“\nDiğer dizide eksik olan sayı: {0}”, EksikSayiyiBul(baskaDizi));
}
}
- verilen bir metnin veya sayının palindrom (tersten okunuşu aynı olan) olup olmadığını kontrol edin
- C# Kodu (Metinler için)
using System;
using System.Linq;
using System.Text;class Program
{
/// <summary>
/// Verilen bir metnin palindrom olup olmadığını kontrol eder.
/// Boşlukları, noktalama işaretlerini ve büyük/küçük harf durumunu yok sayar.
/// </summary>
/// <param name=”metin”>Kontrol edilecek metin.</param>
/// <returns>Palindrom ise true, değilse false döner.</returns>
public static bool MetinPalindromMu(string metin)
{
// 1. Metni “temizle”: Sadece harf ve rakamları bırak, hepsini küçük harfe çevir.
// Bu, “Ey edip, Adana’da pide ye!” gibi cümlelerin doğru kontrol edilmesini sağlar.
var temizStringBuilder = new StringBuilder();
foreach (char karakter in metin)
{
if (char.IsLetterOrDigit(karakter))
{
temizStringBuilder.Append(char.ToLower(karakter));
}
}
string temizMetin = temizStringBuilder.ToString();// Boş metinler palindrom kabul edilebilir.
if (string.IsNullOrEmpty(temizMetin))
{
return true;
}// 2. İki işaretçi (pointer) ile metni kontrol et
int sol = 0;
int sag = temizMetin.Length – 1;while (sol < sag)
{
// Baştaki ve sondaki karakterler eşleşmiyorsa, palindrom değildir.
if (temizMetin[sol] != temizMetin[sag])
{
return false;
}// İşaretçileri ortaya doğru hareket ettir
sol++;
sag–;
}// Döngü bittiğinde tüm karakterler eşleşmiş demektir.
return true;
}// Diğer fonksiyonlar ve Main metodu buraya eklenecek…
C# Kodu (Sayılar için)
/// <summary>
/// Verilen bir sayının palindrom olup olmadığını matematiksel olarak kontrol eder.
/// </summary>
/// <param name=”sayi”>Kontrol edilecek tam sayı.</param>
/// <returns>Palindrom ise true, değilse false döner.</returns>
public static bool SayiPalindromMu(int sayi)
{
// Negatif sayılar palindrom değildir.
// Ayrıca, 0 olmayan ve sonu 0 ile biten sayılar da palindrom olamaz (örn: 120 != 021)
if (sayi < 0 || (sayi % 10 == 0 && sayi != 0))
{
return false;
}int tersCevrilmisSayi = 0;
int orijinalSayi = sayi; // Orijinal değeri karşılaştırma için saklawhile (sayi > 0)
{
int sonBasamak = sayi % 10;
tersCevrilmisSayi = (tersCevrilmisSayi * 10) + sonBasamak;
sayi = sayi / 10;
}// Orijinal sayı ile ters çevrilmiş halini karşılaştır.
return orijinalSayi == tersCevrilmisSayi;
}
- Verilen bir sayının asal olup olmadığını bulan verimli bir fonksiyon yazın.
-
using System;
public class Program
{
/// <summary>
/// Verilen bir sayının asal olup olmadığını verimli bir şekilde kontrol eder.
/// </summary>
/// <param name=”sayi”>Kontrol edilecek sayı.</param>
/// <returns>Sayı asalsa true, değilse false döner.</returns>
public static bool AsalMi(long sayi)
{
// 1. Temel Kontroller
// 2’den küçük sayılar asal değildir.
if (sayi < 2)
{
return false;
}// 2, asal olan tek çift sayıdır.
if (sayi == 2)
{
return true;
}// 2 dışındaki çift sayılar asal değildir.
if (sayi % 2 == 0)
{
return false;
}// 2. Karekök Limiti ve Tek Sayı Kontrolü
// Sayının kareköküne kadar olan TEK bölenleri kontrol etmemiz yeterlidir.
long limit = (long)Math.Sqrt(sayi);
for (long i = 3; i <= limit; i += 2) // i’yi 2 artırarak sadece tek sayıları kontrol et
{
if (sayi % i == 0)
{
// Bir bölen bulunduysa, sayı asal değildir.
return false;
}
}// Döngü bittiğinde hiçbir bölen bulunmadıysa, sayı asaldır.
return true;
}public static void Main(string[] args)
{
Console.WriteLine(“— Asal Sayı Kontrolü —“);int[] testEdilecekSayilar = { 1, 2, 3, 4, 17, 25, 79, 97, 100, 9973 };
foreach (var sayi in testEdilecekSayilar)
{
if (AsalMi(sayi))
{
Console.WriteLine($”{sayi} bir asal sayıdır.”);
}
else
{
Console.WriteLine($”{sayi} bir asal sayı değildir.”);
}
}
}
} - Fibonacci serisinin n’inci elemanını bulan fonksiyonu yazın.
-
using System;
public class Program
{
/// <summary>
/// Fibonacci serisinin n’inci elemanını döngü kullanarak verimli bir şekilde bulur.
/// </summary>
/// <param name=”n”>Serideki istenen elemanın sırası (0’dan başlayarak).</param>
/// <returns>n’inci Fibonacci sayısı.</returns>
public static long FibonacciIterative(int n)
{
// Negatif girdiler için hata yönetimi
if (n < 0)
{
throw new ArgumentException(“Girdi negatif olamaz.”, nameof(n));
}// Temel durumlar
if (n == 0) return 0;
if (n == 1) return 1;long a = 0;
long b = 1;
long sonuc = 0;// 2’den n’e kadar döngü ile seriyi oluştur
for (int i = 2; i <= n; i++)
{
sonuc = a + b; // Bir sonraki eleman, önceki ikisinin toplamıdır
a = b; // Birinci sayıyı ikinci sayı yap
b = sonuc; // İkinci sayıyı yeni sonuç yap
}return b; // n’inci eleman ‘b’ değişkeninde tutulur
}public static void Main(string[] args)
{
Console.WriteLine(“— Fibonacci Serisi (İteratif Yöntem) —“);
int n = 10;
long sonuc = FibonacciIterative(n);
// Serinin 10. elemanı (0’dan sayınca): 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 -> 55 olmalı
Console.WriteLine($”Fibonacci serisinin {n}. elemanı: {sonuc}”);n = 40;
sonuc = FibonacciIterative(n);
Console.WriteLine($”Fibonacci serisinin {n}. elemanı: {sonuc}”);
}
} - Harika sorular. Bu üç soru, C# ve nesne yönelimli programlama (OOP) üzerine yapılan teknik mülakatların temel taşlarıdır. İşte her biri için detaylı ve anlaşılır cevaplar:
1. Interface ile Abstract Class Arasındaki Farklar Nelerdir?
Bu sorunun cevabı, iki yapının temel tasarım amaçlarında yatar: Abstract Class, “bir şeyin ne olduğu” (is-a ilişkisi) üzerine bir temel oluştururken, Interface “bir şeyin ne yapabildiği” (can-do ilişkisi) üzerine bir sözleşme tanımlar.
Aşağıdaki tablo temel farkları özetlemektedir:
Hangi Durumda Hangisini Tercih Edersiniz?
- Abstract Class Tercih Edin, Eğer:
- Birbirleriyle yakından ilişkili bir sınıf ailesi oluşturuyorsanız (Örn:
Kedi
,Kopek
sınıfları için birHayvan
abstract sınıfı). - Türetilecek sınıfların paylaşması gereken ortak ve doldurulmuş metotlar veya alanlar varsa (Örn:
Hayvan
sınıfındakiYas
alanı veyaNefesAl()
metodu). - Sınıflarınızın bir temel “kimliği” varsa ve bu kimlik üzerine bir hiyerarşi kuruyorsanız.
- Birbirleriyle yakından ilişkili bir sınıf ailesi oluşturuyorsanız (Örn:
- Interface Tercih Edin, Eğer:
- Birbirleriyle ilişkisiz olan sınıflara ortak bir yetenek kazandırmak istiyorsanız (Örn:
Kus
,Ucak
,Drone
sınıflarının hepsiIUcabilir
arayüzünü uygulayabilir). - Bir sınıfın birden fazla “tür” veya “davranış” grubuna ait olmasını istiyorsanız (çoklu kalıtım ihtiyacı).
- API’nizin belirli bir sözleşmeye uymasını garanti altına almak ve esnek bir yapı kurmak istiyorsanız (Dependency Injection gibi desenlerde sıkça kullanılır).
- Birbirleriyle ilişkisiz olan sınıflara ortak bir yetenek kazandırmak istiyorsanız (Örn:
2. Polimorfizm (Polymorphism) Nedir? Örnekle Açıklama
Polimorfizm (Çok Biçimlilik), nesne yönelimli programlamanın dört temel prensibinden biridir. En basit tanımıyla, bir nesnenin veya metodun birden fazla formda davranabilme yeteneğidir.
Bu, temel bir sınıf (base class) veya arayüz (interface) referansı üzerinden, ondan türetilmiş farklı nesnelerin kendi özel metotlarını çağırabilmemizi sağlar. Yani, aynı kod parçası farklı nesne türleri için farklı sonuçlar üretebilir.
Gerçek Hayattan Örnek
Bir fabrikada farklı geometrik şekiller ürettiğinizi düşünün: Daire, Kare, Üçgen. Hepsinin ortak bir eylemi vardır: “Çiz”. Ancak her şekil farklı bir şekilde çizilir.
- Temel Sınıf/Arayüz:
Sekil
(içindeCiz()
metodu var) - Türetilmiş Sınıflar:
Daire
,Kare
,Ucgen
- Polimorfizm: Siz elinize bir
Sekil
listesi alıp, her birine “Kendini çiz!” komutunu verirsiniz. Program, o anki şeklin Daire mi, Kare mi olduğunu anlar ve ona uygun çizim işlemini otomatik olarak yapar.
- Abstract Class Tercih Edin, Eğer:
- using System;
using System.Collections.Generic;// 1. Temel Sınıf (Base Class)
public abstract class Sekil
{
// “virtual” anahtar kelimesi bu metodun türetilmiş sınıflar tarafından
// ezilebileceğini (override) belirtir.
public virtual void Ciz()
{
Console.WriteLine(“Bir şekil çiziliyor…”);
}
}// 2. Türetilmiş Sınıflar (Derived Classes)
public class Daire : Sekil
{
// “override” anahtar kelimesi ile temel sınıftaki metodu eziyoruz.
public override void Ciz()
{
Console.WriteLine(“Bir daire çiziliyor: O”);
}
}public class Kare : Sekil
{
public override void Ciz()
{
Console.WriteLine(“Bir kare çiziliyor: []”);
}
}public class Ucgen : Sekil
{
public override void Ciz()
{
Console.WriteLine(“Bir üçgen çiziliyor: /\\”);
}
}// 3. Polimorfizmin Uygulanması
public class Program
{
public static void Main(string[] args)
{
// Tek bir liste, farklı türde nesneleri (ama hepsi “Sekil”) tutabiliyor.
List<Sekil> sekiller = new List<Sekil>();
sekiller.Add(new Daire());
sekiller.Add(new Kare());
sekiller.Add(new Ucgen());
sekiller.Add(new Daire());// Polimorfizmin gücü burada ortaya çıkıyor:
// “sekil” değişkeninin türü derleme zamanında “Sekil” olarak bilinse de,
// çalışma zamanında (runtime) gerçek nesne türü ne ise (Daire, Kare vb.)
// o nesnenin Ciz() metodu çağrılır.
foreach (Sekil sekil in sekiller)
{
sekil.Ciz(); // Aynı kod satırı, farklı çıktılar üretiyor.
}
}
}
SOLID Prensipleri Nelerdir?
SOLID, Robert C. Martin tarafından ortaya atılan ve sürdürülebilir, anlaşılır ve esnek yazılımlar oluşturmayı amaçlayan beş temel tasarım prensibinin kısaltmasıdır.
S – Single Responsibility Principle (Tek Sorumluluk Prensibi)
- Anlamı: Bir sınıfın veya metodun değişmek için sadece tek bir nedeni olmalıdır.
- Açıklama: Her sınıf, sadece bir işlevsellikten veya görevden sorumlu olmalıdır. Örneğin, bir
Musteri
sınıfı hem müşteri bilgilerini tutup hem de bu bilgileri veritabanına kaydetmemelidir. Veritabanı işlemleri içinMusteriRepository
gibi ayrı bir sınıf olmalıdır. Bu, kodun bakımını ve test edilebilirliğini artırır.
O – Open/Closed Principle (Açık/Kapalı Prensibi)
- Anlamı: Yazılım birimleri (sınıflar, metotlar vb.) genişlemeye açık, ancak değişikliğe kapalı olmalıdır.
- Açıklama: Mevcut çalışan bir kodu değiştirmek yerine, sisteme yeni bir özellik eklemek için yeni kodlar (yeni sınıflar, metotlar) yazılmalıdır. Bu genellikle kalıtım veya arayüzler kullanılarak sağlanır. Örneğin, bir sistemde farklı ödeme tipleri varsa, yeni bir ödeme tipi (örn: KriptoPara) eklemek için mevcut
OdemeIslemi
sınıfını değiştirmek yerine,IOdemeYontemi
arayüzünü uygulayan yeni birKriptoParaOdeme
sınıfı oluşturulur.
L – Liskov Substitution Principle (Liskov Yerine Geçme Prensibi)
- Anlamı: Türetilmiş bir sınıf, temel sınıfının yerine herhangi bir değişiklik yapmadan kullanılabilmeli ve programın tutarlılığını bozmamalıdır.
- Açıklama: Eğer bir
Kare
sınıfı,Dikdortgen
sınıfından kalıtım alıyorsa,Dikdortgen
nesnesi beklenen her yerdeKare
nesnesi de sorunsuz çalışmalıdır. EğerDikdortgen
‘inGenislik
veYukseklik
özellikleri birbirinden bağımsız değiştirilebiliyorken,Kare
‘de birini değiştirmek diğerini de değiştiriyorsa, bu durum prensibi ihlal edebilir ve beklenmedik hatalara yol açabilir.
I – Interface Segregation Principle (Arayüz Ayırma Prensibi)
- Anlamı: Bir sınıfa, ihtiyaç duymadığı metotları içeren “şişman” bir arayüzü uygulamaya zorlanmamalıdır.
- Açıklama: Büyük ve her şeyi kapsayan arayüzler yerine, daha küçük, amaca yönelik ve özelleşmiş arayüzler oluşturulmalıdır. Örneğin,
IUcabilir
,IYuzebilir
gibi yetenekleri tek birIHareketEdebilir
arayüzünde toplamak yerine, her birini ayrı arayüzler olarak tanımlamak daha doğrudur. Böylece birBalik
sınıfı sadeceIYuzebilir
arayüzünü uygular, ihtiyaç duymadığıUç()
metodunu implemente etmek zorunda kalmaz.
D – Dependency Inversion Principle (Bağımlılıkların Tersine Çevrilmesi Prensibi)
- Anlamı: Yüksek seviyeli modüller (iş mantığını içeren), düşük seviyeli modüllere (veritabanı, dosya sistemi gibi teknik detaylara) doğrudan bağımlı olmamalıdır. Her ikisi de soyutlamalara (genellikle arayüzlere) bağımlı olmalıdır.
- Açıklama: Sınıflar, somut implementasyonlara değil, arayüzlere veya soyut sınıflara dayanmalıdır. Örneğin, bir
RaporlamaServisi
sınıfı, doğrudan birSqlVeritabani
sınıfına değil,IVeritabani
arayüzüne bağımlı olmalıdır. Bu sayede yarınOracleVeritabani
veyaMongoDb
kullanmak istediğimizdeRaporlamaServisi
sınıfını değiştirmemize gerek kalmaz. Bu prensip, Dependency Injection (DI) tasarım deseninin temelini oluşturur.
- Aşağıdaki gibi iki tablomuz olduğunu varsayalım:
Musteriler
(MusteriID, Ad, Soyad) veSiparisler
(SiparisID, MusteriID, SiparisTarihi, Tutar). Her bir müşterinin toplam sipariş tutarını, en çok harcama yapandan en aza doğru sıralayarak getiren SQL sorgusunu yazar mısınız?” - Beklenen Cevap (Konsept Olarak):
SQL
SELECT M.Ad, M.Soyad, SUM(S.Tutar) AS ToplamHarcama FROM Musteriler M INNER JOIN Siparisler S ON M.MusteriID = S.MusteriID GROUP BY M.MusteriID, M.Ad, M.Soyad ORDER BY ToplamHarcama DESC;