Son hafta yeni bir OOP kavramı eklemiyoruz. Amaç dönem boyunca öğrendiğimiz fikirleri küçük ve sınırları açık bir değişiklikte birlikte kullanmak: nesne durumunu anlamak, sorumluluğu doğru sınıfa vermek, geçerli durumu korumak, nesneler arası ilişkiyi yönetmek ve değişikliğin etkisini açıklamak.
Bu bölümün kapsamı
NoteSınavda sorulur
bir sistemi okurken hangi sınıfın hangi durumu koruduğunu belirleme
birden çok nesneyi değiştiren işlemde nesneler arası tutarlılık
in ve list.remove() işlemlerinin == eşitliğini kullanması
__eq__ eklemenin koleksiyon davranışını da değiştirmesi
invariant için raise, geliştirici kontrolü için assert
iş kuralının hangi sınıfa ait olduğuna sorumlulukla karar verme
tasarım değişikliğini regresyon kontrolleriyle doğrulama
NoteSınav dışı (bilgi amaçlı)
transaction ve geri alma (rollback) mekanizmaları
kalıcı veri saklama ve eşzamanlılık
pytest / unittest ile otomatik test yazımı
Bu başlıklar konunun devamıdır; ileride karşınıza çıkar ama bu derste ezberlemeniz beklenmiyor.
Yeni gereksinim hangi sınıfın sorumluluğuna ait?
Bu bölümde yeni bir konu öğrenmiyoruz. Çalışan küçük bir modele üç gereksinim ekleyip dönemin bütün kararlarını aynı problemde kullanıyoruz. Zor olan kod yazmak değil; kuralı doğru sınıfa koymak ve iki nesnenin durumunu tutarlı bırakmak.
Başlangıç sistemi
WarningBaşlangıç kodu “nihai üretim mimarisi” değildir
Bu model öğretim amacıyla küçüktür. Gerçek bir sistemde birden fazla nesneyi etkileyen işlemler, kalıcı veri ve eşzamanlılık olduğunda transaction gibi daha güçlü mekanizmalar gerektirebilir. Buradaki hedef, önce doğrula → sonra değiştir ilkesini ve sorumluluk sınırlarını görünür hâle getirmektir.
Önce sistemi okuyun
Kod eklemeden şu soruları cevaplayın:
Nesne sorumlulukları
Book hangi durumu koruyor?
Member hangi koleksiyonu yönetiyor ve neden tuple görünümü döndürüyor?
Library neden kitap ve üyeleri sözlükte tutuyor?
Library.borrow() hangi işleri kendi yapıyor, hangilerini nesnelere devrediyor?
Aynı Book nesnesi hem Library.books içinde hem üyenin koleksiyonunda bulunabilir mi? Bu iki ayrı kitap anlamına gelir mi?
Hangi kontroller iki nesne değişmeden önce yapılmalıdır?
Nesneler arası tutarlılık
Tek nesnenin invariant’ını korumak yeterli olmayabilir. Ödünç alma gibi bir işlem hem Book hem Member durumunu değiştirir. İkinci güncelleme başarısız olup birinci değişiklik yapılmış kalırsa sistem yarım güncellenir.
Bu yüzden bu örnekte:
Üye ve kitap bulunur,
Üyenin ödünç alma koşulları kontrol edilir,
Kitabın uygunluğu kontrol edilir,
Ancak bundan sonra iki durum değiştirilir.
ImportantBir sınıfın invariant’ı yetmeyebilir
Bir kullanım senaryosu birden fazla nesnenin durumunu birlikte değiştiriyorsa nesneler arası tutarlılık da ayrı bir tasarım sorusudur.
Kritik sentez: in ve remove() hangi eşitliği kullanıyor?
Şu iki satıra dikkat edin:
if book inself._borrowed_books: ...self._borrowed_books.remove(book)
Liste üyelik kontrolü (in) ve list.remove() eşleşmeyi == eşitliği üzerinden arar. Kendi sınıfımızda __eq__ tanımlamadığımız başlangıç durumunda farklı Book örnekleri, ISBN’leri aynı olsa bile alan anlamında eşit sayılmaz.
Şimdi 12. haftadaki gibi ISBN eşitliği ekleyelim:
class Book: ...def__eq__(self, other):ifnotisinstance(other, Book):returnNotImplementedreturnself.isbn == other.isbn
Artık:
first = Book("978-1", "Python")second = Book("978-1", "Aynı ISBN, başka nesne")print(first is second) # Falseprint(first == second) # True
ve dolayısıyla second in [first] sonucu da True olur.
Warning__eq__ eklemek yalnızca a == b satırını değiştirmez
Eşitlik tanımı, in, list.remove(), liste karşılaştırmaları ve başka koleksiyon işlemlerinin davranışını da değiştirebilir. Book.__eq__’yi ISBN’e göre tanımladığınız anda Member sınıfındaki üyelik/çıkarma mantığının semantiği de sessizce değişir.
Bu kötü olmak zorunda değildir; hatta alan modeliniz için istediğiniz davranış olabilir. Ancak etkiyi bilinçli test etmeniz gerekir.
Mikro deney — eşitliğin yan etkisini görün
Burada remove(probe), listede aynı nesne bulunmasa bile ISBN’e göre eşit kabul edilen registered nesnesini kaldırır. Bu davranışın modeliniz için doğru olup olmadığını tasarım kararı olarak değerlendirin.
assert ne için kullanılmalı?
Ders boyunca küçük beklentileri görünür kılmak için:
assert book.borrowed_by is memberassertlen(member.borrowed_books) ==1
kullanabiliriz. Bu, test düşüncesine iyi bir geçiştir.
Ancak assert üretim girdisi doğrulama mekanizması değildir:
assert amount >0, "Tutar pozitif olmalı"
şeklinde iş kuralı korumak güvenli değildir. Python -O (optimize) seçeneğiyle çalıştırıldığında assert ifadeleri kaldırılabilir.
ImportantInvariant için raise, geliştirici kontrolü için assert
Kullanıcı girdisi, alan kuralı veya nesnenin geçerli durumunu koruyan kontrol normal program davranışının parçasıysaif ...: raise ... kullanın. assert, “programcı olarak burada doğru olduğunu varsaydığım şey gerçekten doğru mu?” türündeki geliştirme/test kontrolleri için uygundur.
Gereksinim 1 — Üye başına en fazla üç kitap
MAX_BORROWED_BOOKS = 3 kuralının Member içinde tutulması güçlü bir adaydır; çünkü üyenin kendi ödünç kitap koleksiyonunun sahibidir. Ancak koordinasyonu yapan Library, durum değişikliklerinden önce member.ensure_can_borrow(book) çağırarak yarım güncelleme riskini azaltır.
Şunları test edin:
1., 2. ve 3. kitap başarıyla alınır,
kitap reddedilir,
reddedilen kitap hâlâ kullanılabilirdir,
üyenin koleksiyonunda yalnızca üç kitap vardır.
Gereksinim 2 — İade işlemi
Nesneler arası işbirliği
İade başlamadan önce şu durumları düşünün:
Üye yok,
Kitap yok,
Kitap zaten kütüphanede,
Kitap başka bir üyede,
Kitap üyeyi gösteriyor ama üyenin listesinde bulunmuyor.
Başarılı iade sonunda:
assert book.is_availableassert book notin member.borrowed_books
beklenir. Bu assertlar test kontrolüdür; return_book() içindeki iş kurallarının yerine geçmez.
Gereksinim 3 — ISBN’e göre eşitlik
Book.__eq__ davranışını ISBN’e göre ekleyin. Sonra özellikle aşağıdaki regresyonları çalıştırın:
Aynı ISBN’li iki farklı nesne == ile eşit, is ile farklı olmalı.
Aynı ISBN’li ikinci nesne, üyelik kontrolünde ilk nesneyle eşleşmeli.
remove() davranışının artık ISBN eşitliğinden etkilendiğini gösterin.
Bu davranışın kütüphane modelinizde istenen semantik olup olmadığını kısa gerekçeyle açıklayın.
Bu görev 6. haftadaki kimlik, 9. haftadaki nesne koleksiyonu ve 12. haftadaki eşitlik bilgisini aynı yerde birleştirir.
Gözetimli bütünleştirici görev
Başlangıç sistemine şu küçük değişiklikleri uygulayın:
Üye başına en fazla üç kitap kuralını doğrulayın,
Güvenli iade davranışını tamamlayın,
Book.__eq__’yi ISBN üzerinden tanımlayın,
İç koleksiyonu dışarıdan doğrudan değiştirmeyi engelleyin,
Başarılı ve başarısız akışları küçük kontrollerle doğrulayın.
Çalışır kod teslimi zorunludur. En az şu senaryoları otomatik olarak kontrol eden çalışır bir dosya teslim edin:
Normal ödünç alma,
Aynı kitabı tekrar alma,
Dördüncü kitap sınırı,
Başarılı iade,
Yanlış üyeden iade,
Aynı ISBN’li farklı Book örnekleriyle eşitlik/üyelik davranışı.
Alan kurallarını assert ile değil raise ile koruyun; assertları yalnızca test/sonuç doğrulaması için kullanın.
Kısa tasarım savunması
Kodun altına en fazla 150 kelimelik cevap ekleyin:
Ödünç alma sınırı neden Member sorumluluğudur?
Library neden yine de ön koşulları koordine eder?
Book.__eq__ eklemek koleksiyon davranışını nasıl değiştirdi?
İç koleksiyon neden doğrudan mutable liste olarak dışarı verilmedi?
Hangi kontroller raise, hangileri assert ile ifade edildi ve neden?
Deneme sınavı — 20 madde
Bu 20 madde final biçiminin birebir örneğidir: her madde beş şıklıdır ve dönemin tamamını tarar. Önce kendin çöz, sonra cevap anahtarındaki gerekçeleri oku.
1. C’de int age = 20; yazarken Python’da yalnızca age = 20 yazmak neyi anlatır?
A. Tür yalnızca print() çağrısında belirlenir
B. Python age adını kendiliğinden int olarak bildirir ve başka tür atanamaz
C. Python’da tür kavramı yoktur; bütün değerler aynı biçimde saklanır
D. Python bütün sayıları float olarak tutar, bu yüzden bildirim gerekmez
E. Değerin bir türü vardır; tür bilgisi değişken adına değil, adın bağlandığı değere aittir
2. Aşağıdaki program score = 70 iken ne yazdırır?
if score >=85: result ="AA"elif score >=70: result ="BB"else: result ="Başarısız"print(result)
A.BB
B. Hiçbir şey yazmaz
C.BB ve Başarısız
D.Başarısız
E.AA
3. Bir metindeki benzersiz kelimeleri tutmak için en uygun koleksiyon hangisidir?
A.tuple; değiştirilemez olduğu için tekrar eklenemez
B.set; tekrarları kendiliğinden eler ve üyelik sorusuna doğrudan cevap verir
E. Hata verir; dönüş değeri olmayan bir çağrı bir değişkene atanamaz
5.with open("notes.txt", "r", encoding="utf-8") as file: yazımının elle open() / close() çiftine göre avantajı nedir?
A. Dosya yoksa kendiliğinden oluşturur
B. Kodlama belirtmeyi gereksiz kılar
C. Dosyanın içeriğini kendiliğinden satırlara böler
D. Blok tamamlandığında dosya, hata oluşsa bile kapatılır; close() çağrısını unutma riski kalmaz
E. Dosyayı belleğe tümüyle yükleyerek okumayı hızlandırır
6.score = 80 ve ardından score = 90 yazıldığında ne olur?
A.score adlı kutunun içindeki 80 değeri 90 ile üzerine yazılır
B. İki ayrı score değişkeni oluşur
C. Hata verir; bir ada iki kez atama yapılamaz
D. 80 değeri bellekten hemen silinir ve score geçersiz olur
E.score adı önce bir nesneye, sonra başka bir nesneye bağlanır; ilk nesnenin içi değiştirilmez
7. Sınıf ile nesne (örnek) arasındaki fark nedir?
A. Sınıf, belirli türde nesnelerin hangi duruma ve davranışa sahip olacağını tanımlar; nesne o tanımdan üretilmiş, kendi durumunu taşıyan çalışma anı örneğidir
B. Sınıf yalnızca veriyi, nesne yalnızca davranışı tutar
C. Nesne sınıfın kopyasıdır; sınıf değişirse nesne değişmez
D. Her sınıftan yalnızca bir nesne üretilebilir
E. Sınıf çalışma anında, nesne yazım anında var olur
8. Değişmez koşul (invariant) nedir?
A. Sınıfın bütün örneklerinde ortak olan sınıf niteliğidir
B. Nesnenin geçerli kabul edildiği her anda doğru olması gereken kuraldır
C. Metotların kaç parametre alacağını belirleyen sözleşmedir
D. Nesne üretildikten sonra hiç değişmeyen nitelik değeridir
E. Programın hiç hata vermeyeceğini garanti eden kontroldür
class Book:def__init__(self, isbn):self.isbn = isbndef__eq__(self, other):ifnotisinstance(other, Book):returnNotImplementedreturnself.isbn == other.isbnregistered = Book("978-1")probe = Book("978-1")books = [registered]print(probe in books)books.remove(probe)print(books)
A.True ve [Book]
B.True ve [probe]
C.True ve []
D.False ve [registered]
E.False ve ValueError
20.Book.__eq__ metodunu ISBN’e göre tanımlamak yalnızca a == b satırını mı etkiler?
A. Evet; __eq__ yalnız açık karşılaştırma ifadelerinde kullanılır
B. Hayır; ayrıca is operatörünün davranışı da değişir
C. Hayır; __str__ çıktısı da değişir
D. Hayır; in, list.remove(), liste karşılaştırmaları ve başka koleksiyon işlemlerinin davranışı da değişir
E. Evet; ancak yalnız aynı sınıfın örnekleri karşılaştırılırsa
TipCevaplar ve gerekçeler
1 — Doğru: E.20 bir int nesnesidir. age yalnızca o nesneye bağlanan addır; ad önceden bir türe bildirilmez.
A yanlış: Tür değerin kendisine aittir ve print() çağrılmasa da vardır.
B yanlış: Aynı ad sonradan age = "yirmi" ile bir str değere bağlanabilir; bildirim yoktur.
C yanlış:type(20)int verir. Tür vardır, yalnızca bildirimi adda değil değerdedir.
D yanlış:type(20)int döndürür; int ve float ayrı türlerdir.
2 — Doğru: A. İlk koşul yanlıştır; ikinci koşulda 70 >= 70 doğru olduğu için zincir orada durur.
B yanlış:else dalı da bulunduğu için result her durumda bir değere bağlanır.
C yanlış:elif zincirinde yalnızca bir dal çalışır; ilk doğru koşuldan sonra zincir biter.
D yanlış:else yalnızca önceki koşulların hepsi yanlışsa çalışır.
E yanlış:70 >= 85 yanlıştır; ilk dal seçilmez.
3 — Doğru: B. Küme aynı değeri bir kez tutar; sıra önemli değilse en doğrudan seçimdir.
A yanlış: Değişmezlik tekrar içermediği anlamına gelmez; ("a", "a") geçerlidir.
C yanlış: Liste aynı değeri birden çok kez tutar; benzersizliği elle sağlamak gerekir.
D yanlış: Metin bir koleksiyon kabı değildir; kelimeleri ayrı ayrı yönetmez.
E yanlış: Sözlük kullanılabilir ama değer tarafı boşa gider; yalnız üyelik için küme yeterlidir.
4 — Doğru: C. İlk satırı fonksiyonun kendi print() çağrısı üretir. Fonksiyon return içermediği için dönüş değeri Nonedır.
A yanlış: Ekrana yazmak değer döndürmek değildir; taşınan bir sonuç yoktur.
B yanlış: Fonksiyon gövdesindeki print() de çalışır.
D yanlış: Çağrı sırasında gövdedeki print() çıktısı da görünür.
E yanlış: Atama geçerlidir; atanan değer Nonedır.
5 — Doğru: D.with bloğu çıkışta temizliği kendisi yapar; istisna yükselse de dosya kapanır.
A yanlış: Dosyanın oluşup oluşmayacağını kip belirler; "r" kipinde hata yükselir.
B yanlış:encoding yine açıkça yazılmalıdır.
C yanlış: Satır dolaşımı ayrı bir işlemdir.
E yanlış: Okuma biçimini değiştirmez; yaptığı iş kaynak yönetimidir.
6 — Doğru: E. Atama bir kutunun içeriğini değiştirmez; adın hangi nesneyi gösterdiğini değiştirir.
A yanlış: Kutu modeli burada yanıltır; int nesneleri değiştirilemez ve içleri güncellenmez.
B yanlış: Tek bir ad vardır; yalnız bağlandığı nesne değişir.
C yanlış: Yeniden atama geçerli ve olağandır.
D yanlış: Ad her zaman geçerli bir nesneyi gösterir; eski nesnenin akıbeti ayrı bir konudur.
7 — Doğru: A. Sınıf bir tür tanımıdır; her örnek kendi nitelik değerlerini taşır.
B yanlış: Sınıf hem durumun biçimini hem davranışı tanımlar.
C yanlış: Örnek bir kopya değildir; metotlarını sınıftan okur.
D yanlış: İstenildiği kadar örnek üretilebilir.
E yanlış: İkisi de çalışma anında vardır; sınıf tanımı da yürütülen bir ifadedir.
8 — Doğru: B.balance >= 0 veya 0 <= score <= 100 gibi kurallar nesnenin ne anlama geldiğinin parçasıdır; yalnız bir doğrulama ayrıntısı değildir.
A yanlış: Sınıf niteliği paylaşılan veridir; kural değildir.
C yanlış: İmza sözleşmesi ayrı bir konudur.
D yanlış: Değişmeyen değer sabittir; invariant değerin değil, kuralın sabitliğidir.
E yanlış: İnvariant korunurken hata yükseltilebilir; amaç geçersiz durumu engellemektir.
9 — Doğru: C. Kompozisyonda nesne kopyalanmaz; referans tutulur. Müşterinin durumu değişince sipariş üzerinden de yeni değer görülür.
A yanlış: Yazdırılan, sınıf adı değil nitelik değeridir.
B yanlış: Python argümanı kopyalamaz; aynı nesne paylaşılır.
D yanlış: Zincirleme nitelik erişimi geçerlidir.
E yanlış:name niteliği bir metne bağlıdır.
10 — Doğru: D.Developer gövdesi boş olsa da __init__ ve describe üst sınıftan devralınır. Bir Developer aynı zamanda Employee tür ilişkisindedir.
A yanlış:Developer metodu override etmemiştir; üst sınıfın metni kullanılır.
B yanlış: Boş gövdeli sınıf geçerlidir ve örneklenebilir.
C yanlış:describe üst sınıfta tanımlıdır ve bulunur.
E yanlış:isinstance() üst sınıfları da dikkate alır.
11 — Doğru: E. Döngü nesnenin tam türünü bilmeden send() çağırır; her nesne davranışı kendi biçiminde gerçekleştirir.
A yanlış: Python listeleri karışık türleri tutabilir.
B yanlış: Döngü iki tur döner ve her turda yazdırır.
C yanlış: Çağrı, listedeki her nesnenin kendi sınıfındaki metoda gider.
D yanlış: Ortak üst sınıf gerekmez; her nesne send sunmaktadır.
12 — Doğru: A.print(obj) ve str(obj) mümkün olduğunda __str__() sonucunu kullanır.
B yanlış: Bu bir __repr__ çıktısı biçimidir; burada __repr__ tanımlı değildir.
C yanlış:print() her nesneyi kabul eder ve metin temsilini ister.
D yanlış: Varsayılan temsil ancak __str__ ve __repr__ tanımlı değilse görünür.
E yanlış:__str__ bir metin döndürür ve print onu yazar.
13 — Doğru: B. İstenirse paket yüklenirken çalışacak kodu veya dışarıya sunulacak adları da içerebilir; başlangıçta boş bırakmak yeterlidir.
A yanlış: Boş dosya da sınırı belirtmeye yeter.
C yanlış: Yerel paketlerde de kullanılır.
D yanlış: Sınıflar ayrı modüllerde durur.
E yanlış: Paket çalıştırma için __main__.py kullanılır.
14 — Doğru: C. İç mutable listeyi döndürmek 9. haftadaki kapsülleme deliğini açar; dış kod append ile kuralları atlayabilirdi.
A yanlış: Eşitlik dönüş türünden bağımsızdır.
B yanlış: Sayı değişir; sabit olan, dışarı verilen görünümün değiştirilemezliğidir.
D yanlış: Gerekçe başarım değil, arayüz sözleşmesidir.
E yanlış: Demet içindeki Book nesneleri hâlâ değiştirilebilir; korunan koleksiyonun kendisidir.
15 — Doğru: D. Koleksiyonlar nesneleri kopyalamaz, referans tutar. Nesnenin durumu değişince iki yerden de aynı durum görülür.
A yanlış: Tersine, aynı nesneyi paylaşmak tutarlılığı korur.
B yanlış: Koleksiyona ekleme kopya üretmez.
C yanlış: Ödünç durumu is_available gibi bir nitelikle izlenir.
E yanlış: Eşitlik tanımıyla ilgisi yoktur.
16 — Doğru: E. İkinci güncelleme başarısız olup birincisi yapılmış kalırsa sistem yarım güncellenir. Önce doğrula, sonra değiştir ilkesi burada nesneler arası ölçekte uygulanır.
A yanlış: Hata gizlenir ve yarım durum kalıcı olur.
B yanlış: Her nesne kendi invariant’ını korusa da aralarındaki tutarlılık ayrı bir sorudur.
C yanlış:assert bir iş kuralı koruması değildir ve kontrol yine geç kalır.
D yanlış: Geri alma kodu kolayca eksik kalır; yarım güncelleme riski sürer.
17 — Doğru: A. Her nesne tek başına geçerli kalsa bile, aralarındaki ilişki bozulabilir: kitap üyeyi gösterirken üyenin listesinde bulunmamak gibi.
B yanlış: Böyle bir yerleşik mekanizma yoktur; bu yüzden sıra önemlidir.
C yanlış: Bu “her şeyi yapan merkez” üretir; kurallar sahiplerinde kalmalıdır.
D yanlış: Tek nesne invariant’ı hâlâ gereklidir; yalnız yeterli değildir.
E yanlış: İlişki kurulmadan işbirliği olmaz.
18 — Doğru: B. Liste üyelik kontrolü ve remove() değer eşitliğine başvurur. Kendi sınıfımızda __eq__ yoksa farklı örnekler ISBN’leri aynı olsa bile eşit sayılmaz.
A yanlış: Aranan değer, konum değil.
C yanlış: Eşitlik tanımlıysa kimlik yeterli değildir; == kullanılır.
D yanlış: Hash set ve dict yapılarında kullanılır; liste araması değer eşitliğine bakar.
E yanlış: Metin temsili karşılaştırmada kullanılmaz.
19 — Doğru: C.in ve remove() ISBN eşitliğini kullanır. Listede aynı nesne bulunmasa bile eşit kabul edilen registered kaldırılır.
A yanlış:remove() eşleşen elemanı gerçekten çıkarır.
B yanlış: Listeye probe hiç eklenmemiştir.
D yanlış: Eşitlik kimliğe değil ISBN’e bağlanmıştır.
E yanlış:__eq__ tanımlı olduğu için eşleşme bulunur.
20 — Doğru: D.Member sınıfındaki üyelik ve çıkarma mantığının semantiği sessizce değişir. Bu istenen davranış olabilir ama etkisi bilinçli test edilmelidir.
A yanlış: Koleksiyon işlemleri de aynı metoda başvurur.
B yanlış:is her zaman kimliği sorar ve __eq__ tanımından etkilenmez.
C yanlış: Metin temsili ayrı bir metottur.
E yanlış: Etki, tür kontrolünden bağımsız olarak koleksiyon işlemlerine yayılır.
Dönem özeti
İyi nesne tasarımı yalnızca sınıf yazmak değil, durum değişimlerinin sorumluluğunu ve sırasını yönetmektir.
Birden fazla nesneyi değiştiren işlemde nesneler arası tutarlılık ayrıca düşünülmelidir.
__eq__ tanımı in ve remove() gibi koleksiyon davranışlarını da etkiler.
Kimlik ve alan eşitliği farklı sorulardır.
assert geliştirici/test kontrolüdür; python -O ile kaldırılabildiği için iş kuralı doğrulaması değildir.
Kapsülleme mutable iç koleksiyonları da kapsar.
Dönemin hedefi yeni terim ezberlemek değil, küçük bir değişikliği gerekçeli, çalışır ve doğrulanmış biçimde yapabilmektir.
Bu bölümün kazanımları
Bu bölümü bitiren öğrenci:
Bir sistemi okurken hangi sınıfın hangi durumu koruduğunu belirler.
Birden çok nesneyi değiştiren işlemde nesneler arası tutarlılığı gözetir.
in ve list.remove() işlemlerinin == eşitliğini kullandığını gösterir.
__eq__ eklemenin koleksiyon davranışını da değiştirdiğini fark eder ve etkiyi sınar.
İnvariant için raise, geliştirici kontrolü için assert ayrımını uygular.
Bir iş kuralının hangi sınıfa ait olduğuna sorumluluk gerekçesiyle karar verir.
Bir tasarım değişikliğini regresyon kontrolleriyle doğrular.