Ek: Tasarım kararları
Tasarım kararı alıştırmaları
Bu sayfada class yazma alıştırması yapmayacaksınız. Sorular, bir veriyi ya da davranışı neden belirli bir nesneye koyduğunuzu gerekçelendirmenizi ister. Bazı soruların tek ve tartışmasız bir doğrusu yoktur. Böyle sorularda iyi bir cevap gereksinimi açıklar, öteki seçeneğin getireceği sorunu söyler ve sorumluluğu neden o sınıfa verdiğini savunur.
1. “Sorumluluk kime ait?”: 20 kısa karar
Her maddede bir seçenek işaretleyin ve en az bir cümlelik gerekçe yazın. Yalnız harf yazılan cevap eksik sayılır.
1
Siparis, SiparisSatiri, Urun var. toplam_tutar() nerede olmalı?
A) Urun
B) Siparis
C) ekrandaki menü kodu
2
Siparişe yüzde indirimi uygulayan kural kampanyaya göre sık değişiyor. indirim_tutari() için hangisiyle başlamak daha doğru?
A) Siparis içinde sabit bir if zinciri
B) indirimi ayrı bir IndirimPolitikasi hesaplar, sipariş onu kullanır
C) Urun sınıfı
3
Fatura numaraları tek bir merkezden, hiçbiri tekrarlanmayacak biçimde sırayla veriliyor. Numarayı vermek en doğal olarak kimin işi?
A) her Siparis nesnesi kendi sayacını tutar
B) FaturaNumaratoru gibi tek bir sınıf ya da servis
C) Musteri
4
BankaHesabi.para_cek() bakiyenin negatife düşmesini engelleyecek. Kontrol nerede yapılmalı?
A) BankaHesabi
B) kullanıcı arayüzü
C) yalnızca çağıran kod
5
Rezervasyon başlangıç ve bitiş zamanını tutuyor. sure_dakika() nerede olmalı?
A) Rezervasyon
B) Musteri
C) global yardımcı fonksiyon zorunludur
6
Kutuphane, Uye ve KitapKopyasi var. Barkoda göre kitabı, numaraya göre üyeyi bulup ödünç verme işini yürüten odunc_ver() hangi sınıfta olmalı?
A) KitapKopyasi
B) Kutuphane
C) Uye
7
Bir KitapKopyasinın şu anda ödünçte olup olmadığını kim bilmelidir?
A) KitapKopyasi
B) yalnız Kutuphane
C) ekrandaki liste
8
Öğrencinin ortalaması yalnız kendi notlar listesinden hesaplanıyor. Bu hesap için en doğal yer hangisi?
A) Ogrenci
B) Derslik
C) DosyaOkuyucu
9
Sepete yeni ürün satırı eklenirken bir kural uygulanacak: aynı ürün tekrar eklenirse var olan satırla birleştirilecek. urun_ekle() nerede olmalı?
A) Sepet
B) Urun
C) Musteri
10
Bir ürünün fiyatı negatif olamaz. fiyat_degistir() doğrulaması nerede olmalı?
A) Urun
B) her ekran ayrı ayrı kontrol eder
C) CSV dosyası
11
Musteri bir Adres nesnesine sahip. Siparişin teslimat şehrini bilmesi gerekiyor. Hangi yaklaşım daha kontrollü?
A) Siparis, musteri.adres.sehir zincirini her yerde doğrudan kullanır
B) Musteri.teslimat_sehri() işi adrese devreder (delegation); sipariş bu metodu çağırır
C) şehir Siparis içine kopyalanmak zorundadır
12
Sipariş onaylanınca e-posta gönderilecek. SMTP (e-posta gönderme protokolü) ayrıntıları nereye konmalı?
A) Siparis.onayla() içine doğrudan
B) bildirim ya da iletişim servisine; sipariş yalnız kendi durumunu değiştirir
C) Urun
13
Siparis.onayla() taslak siparişi onaylı duruma geçiriyor. Durum geçişi kuralı nerede olmalı?
A) Siparis
B) NotificationService
C) HTML şablonu
14
Siparişler PDF ve CSV dosyası olarak dışa aktarılacak. Dosyayı biçimlendirme işi için hangisiyle başlamak daha doğal?
A) Siparis içine to_pdf(), to_csv(), to_xlsx() eklemek
B) ayrı bir rapor ya da dışa aktarma (export) bileşeni
C) Musteri
15
Bir derslikteki öğrencilerin not ortalaması ve en yüksek not hesaplanacak. Gereken bilgi bütün öğrenci koleksiyonunda. Bu metot nerede daha doğal durur?
A) tek tek Ogrenci
B) Derslik/NotDefteri gibi koleksiyonu yöneten nesne
C) Urun
16
Oda kendi kapasitesini biliyor; bir rezervasyon 30 kişilik yer istiyor. “Bu oda bu grubu alır mı?” sorusunu cevaplayacak bilgi en doğal olarak kimde?
A) Oda
B) RezervasyonFormu
C) yazdırma fonksiyonu
17
Bir sensör nesnesi kendi seri numarasını ve son ölçümünü tutuyor. son_okuma_gecerli_mi() yalnız bu iki bilgiye dayanıyor. Nerede olmalı?
A) Sensor
B) Dashboard
C) veritabanı bağlantısı
18
Bir aracın yakıt tüketimi hesabı yalnız Yolculuk nesnesinin mesafe ve kullanılan yakıt değerlerine dayanıyor. ortalama_tuketim() için en doğal yer hangisi?
A) Yolculuk
B) Arac
C) Surucu
19
Bir öğrenci aynı derse iki kez kaydedilememeli. Ders kayıtlarını ayrı bir KayitDefteri koleksiyonu yönetiyorsa, aynı kaydın ikinci kez eklenip eklenmediğini kontrol etmek nerede daha doğal?
A) KayitDefteri
B) her Ders nesnesi
C) terminal menüsü
20
Siparis ödeme tutarını biliyor; KrediKartiOdeme ve NakitOdeme sınıflarının ikisinde de aynı ode(tutar) metodu var. Ödemenin, yönteme göre değişen kısmı nerede olmalı?
A) Siparis içinde ödeme türüne göre uzun if zinciri
B) ödeme yöntemi nesnesinde; sipariş ortak ode() davranışını çağırır
C) Musteri.ad
- B. Sipariş toplamı, siparişin bütün satırlarından hesaplanır.
- B. Kampanyaya göre sık değişen kural ayrı bir politika nesnesindeyse onu değiştirmek kolaylaşır. Kural tek, küçük ve sabitse A da savunulabilir.
- B. Her sipariş kendi sayacını tutarsa numaraların bütün sistemde tekrarlanmayacağını garanti edemezsiniz. Numaraları tek merkezden veren bir sınıf ya da servis, bu işin kimde olduğunu açıkça gösterir.
- A. Bakiye invariantını hesabın kendisi korumalıdır.
- A. Gerekli iki değer rezervasyondadır.
- B. Kitabı ve üyeyi bulmak, işlemi yürütmek için gereken bilgi kütüphanededir. Kopya ise kendi ödünç durumunu yine kendisi koruyabilir.
- A. Ödünçte olup olmamak kopyanın kendi durumudur.
- A. Hesap yalnız öğrencinin kendi notlarına dayanıyorsa metot da öğrencide durabilir.
- A. Satır eklerken uygulanan tekrar kuralını, satırları yöneten sepet korur.
- A. Fiyatının geçerli kalmasından ürünün kendisi sorumludur.
- B. Müşteri işi adrese devrettiği için sipariş, adresin iç yapısına gereksiz yere bağımlı olmaz. Eski adresin saklanması gerekiyorsa C’deki gibi bir anlık kopya (snapshot) da savunulabilir.
- B. Siparişin durumu ile e-posta gönderme kodu farklı nedenlerle değişir.
- A. Siparişin hangi duruma geçebileceği, siparişin kendi kuralıdır.
- B. Her dışa aktarma biçimi için
Siparise ayrı metot eklenirse sınıf, dosya biçimlendirme ayrıntılarıyla şişer. - B. Bütün koleksiyona dayanan bir özet, koleksiyonu yöneten nesnede daha doğal durur.
- A. Kapasite bilgisi odadadır. Rezervasyonu yürütme işi başka bir yerde kalabilir.
- A. Gerekli bilgi sensördeyse sorgu da sensörde durmalıdır.
- A. Hesap yolculuğun iki niteliğine dayanıyor. Tüketim hesabı araç modeline göre değişiyorsa B de savunulabilir.
- A. Tekrar kontrolü kayıtları tutan koleksiyonda yapılırsa, kayıt hangi yoldan eklenirse eklensin aynı kuraldan geçer.
- B. Aynı çağrının nesneye göre farklı çalışması polimorfizmin tipik kullanımıdır.
2. “Bu kalıtım neden yanlış?”: 8 vaka
Her vakada üç şeyi yazın: (1) bu sınıf hiyerarşisi hangi kullanımda bozulur, (2) yerine kompozisyon ya da daha dar bir sözleşme nasıl kurulur, (3) siz bu problemde hangisini seçerdiniz?
class Araba(Motor): yalnız motoruncalistir()kodunu yeniden kullanmak için yazılmış.class Penguen(UcanKus): üst sınıf her kuştauc()metodu olmasını şart koşuyor.- Mutable
DikdortgensınıfındanKaretüretilmiş;genislikveyukseklikayrı ayrı değiştirilebiliyor. class IsYigini(list): iş yığınında yalnızpush/popişlemlerine izin verilmeli, ama dış kodinsert, dilim ataması vesort()de kullanabiliyor.class PdfFatura(Fatura): tek fark çıktı biçimi; aynı faturanın HTML, PDF ve CSV çıktısı da alınabilmeli.class Calisan(VeritabaniBaglantisi): yalnızsave()metodunu tekrar kullanmak için yazılmış.class OnlineSiparis(EmailGonderici): sipariş onaylandığında e-posta gönderebilmek için e-posta gönderen sınıftan kalıtım yapılmış.class SicaklikSensoru(list): ölçümleri saklamak içinlist’ten türetilmiş; listenin bütün metotları sensörün public arayüzüne girmiş.
- 1: Araba motor değildir; motora sahiptir → kompozisyon.
- 2: “Bütün kuşlar uçar” sözleşmesi yanlış bir genellemedir → yalnız uçan türler için daha dar bir
Ucandavranışı ya da farklı bir kompozisyon. - 3:
Dikdortgen, genişliğin ve yüksekliğin birbirinden bağımsız değiştirilebileceğine söz verir.Karebu sözü tutamaz; bu yüzdenDikdortgenbeklenen her yerdeKarekullanılamaz. Değiştirilemez (immutable) değer nesneleri ya da iki ayrı tür düşünülebilir. - 4:
list’ten türetince iş yığınında olmaması gereken metotlar da gelir → listeyi ya dadeque’yu sınıfın içinde tutun (kompozisyon). - 5: PDF bir fatura türü değil, faturanın çıktı biçimidir → çıktıyı ayrı bir exporter ya da renderer sınıfı hazırlasın.
- 6: Çalışan bir veritabanı bağlantısı değildir → kaydetme işini yapan ayrı bir repository ya da servis nesnesini içeride kullanın (kompozisyon).
- 7: Sipariş bir e-posta gönderici değildir → siparişe bir bildirim nesnesi verin, e-posta işini ona devretsin (delegation).
- 8: Sensör bir liste değildir → ölçüm listesini içeride tutun, dışarıya yalnız gereken metotları açın.
3. Invariant bulma: 6 sınıf
Her sınıf için en az iki invariant yazın. Invariant (değişmez koşul), nesnenin her an uyması gereken kuraldır. Sonra her kuralın hangi metotta korunacağını belirtin: __init__, property setter, durumu değiştiren bir metot ya da koleksiyona ekleme yapan metot.
A: Rezervasyon(baslangic, bitis, kisi_sayisi)
İpuçları: zaman sırası, kişi sayısı.
B: Urun(kod, fiyat, stok)
İpuçları: fiyat ve stok aralığı, ürün kodunun boş olmaması.
C: BankaHesabi(iban, bakiye)
Bu basit modelde eksi bakiyeye izin verilmediğini varsayın.
E: OdaRezervasyonu(oda, kisi_sayisi)
Odanın kapasitesi oda.kapasite ile okunabiliyor. Kişi sayısı pozitif olmalı ve kapasiteyi aşmamalı.
F: DersKayitDefteri()
Aynı (ogrenci_no, ders_kodu) çifti yalnız bir kez bulunabilir; eklenen ders kodu boş olamaz.
- A:
bitis > baslangic,kisi_sayisi > 0. - B:
fiyat >= 0,stok >= 0,kod.strip()boş değil. - C:
bakiye >= 0,ibanboş değil;para_cek()kontrolü bakiyeyi değiştirmeden önce yapar. - D:
0 <= puan <= 100,ogrenci_nogeçerli ve boş değil. - E:
kisi_sayisi > 0,kisi_sayisi <= oda.kapasite. - F: kayıt anahtarı benzersiz, ders kodu boş değil; tekrar kontrolü koleksiyona ekleme yapan metotta yapılır.
Aynı kontrolü hem __init__’e hem setter’a ayrı ayrı yazmayın. Mümkünse ikisi de aynı doğrulama kodunu kullansın.