Üniversitede C ++ öğrenirken öğretim görevlimle de benzer bir tartışmayı hatırlıyorum. Bir değişkeni halka açık hale getirdiğimde alıcıları ve ayarlayıcıları kullanma noktasını göremedim. Şimdi yılların tecrübesiyle daha iyi anlıyorum ve sadece “kapsüllemeyi sürdürmek” demekten daha iyi bir sebep öğrendim.
Alıcıları ve ayarlayıcıları tanımlayarak tutarlı bir arayüz sağlarsınız, böylece uygulamanızı değiştirmek isterseniz bağımlı kodları kırmanız daha az olasıdır. Bu, özellikle sınıflar bir API ile maruz kaldığınızda ve diğer uygulamalarda veya 3. şahıslar tarafından kullanıldığında önemlidir. Peki ya alıcı ya da düzenleyiciye giren şeyler?
Alıcılar genellikle bir değere erişim için basit ve salak bir geçiş yolu olarak uygulandığından daha iyidir, çünkü bu davranışlarını tahmin edilebilir kılar. Genel olarak söylüyorum, çünkü hesaplamaların manipüle ettiği değerlere ve hatta koşullu kodlara erişmek için alıcıların kullanıldığı durumlar gördüm. Tasarım zamanında kullanmak için görsel bileşenler yaratıyorsanız, ancak çalışma zamanında görünüşte kullanışlı görünüyorsa, genellikle çok iyi değil. Ancak bunun arasında basit bir yöntem kullanmak arasında hiçbir fark yoktur, ancak bir yöntem kullandığınızda, bir yöntemi daha uygun şekilde adlandırmanız daha olasıdır; bu nedenle, "alıcı" işlevinin kodu okurken daha belirgin olması gerekir.
Aşağıdakileri karşılaştırın:
int aValue = MyClass.Value;
ve
int aValue = MyClass.CalculateValue();
İkinci seçenek, değerin hesaplandığını açıkça belirtirken, ilk örnek, değerin kendisi hakkında hiçbir şey bilmeden, yalnızca bir değer döndürdüğünüzü söyler.
Belki aşağıdakilerin daha net olacağını iddia edebilirsiniz:
int aValue = MyClass.CalculatedValue;
Ancak sorun, değerin zaten başka bir yerde manipüle edildiğini varsayıyor olmanızdır. Bu nedenle, bir alıcı durumunda, bir değeri döndürürken başka bir şeyin devam edebileceğini varsayırken, bir mülk bağlamında böyle şeyleri açıklığa kavuşturmak zordur ve mülk adları asla fiil içermemelidir Aksi takdirde, bir bakışta kullanılan ismin erişildiğinde parantez ile süslenmesi gerekip gerekmediğini anlamak zorlaştırır.
Ancak ayarlayıcılar biraz farklıdır. Bir pasif sahibinin, bir mülke gönderilen verileri doğrulamak için bazı ek işlemler sağlaması, bir değerin ayarlanması mülkün tanımlanmış sınırlarını ihlal ederse bir istisna atması tamamen uygundur. Bununla birlikte, bazı geliştiricilerin ayarlayıcılara işleme eklemesiyle ilgili sorun, ayarlayıcıyı biraz daha fazla yapmak için, her zaman bir şekilde verinin hesaplanması ya da manipülasyonu yapmak gibi bir cazibenin olmasıdır. Burası, bazı durumlarda tahmin edilemeyen veya istenmeyen olabilecek yan etkileri bulabileceğiniz yerdir.
Belirleyiciler durumunda, her zaman verilere olabildiğince az yapmak için basit bir kural uygularım. Örneğin, genellikle sınır testlerine ve yuvarlama işlemlerine izin vereceğim, böylece gerektiğinde istisnaları ortaya çıkarabilirim veya makul bir şekilde önlenebilecekleri gereksiz istisnalardan kaçınabilirim. Kayan nokta özellikleri, bir istisna oluşturmaktan kaçınmak için aşırı ondalık basamakları yuvarlamak isteyebileceğiniz, buna karşın aralık değerlerinde birkaç ek ondalık basamakla girilmesine izin vermek isteyebileceğiniz iyi bir örnektir.
Setter girişinde bir çeşit manipülasyon uygularsanız, alıcı ile aynı problemi yaşarsınız, diğerlerini setterin ne yaptığını bilmesini sağlamak, sadece adlandırarak zorlaşır. Örneğin:
MyClass.Value = 12345;
Bu, ayarlayıcıya verildiğinde değere ne olacağı hakkında bir şey söylüyor mu?
Peki ya:
MyClass.RoundValueToNearestThousand(12345);
İkinci örnek, verilerinize tam olarak ne olacağını size söylerken, birincisi, değerinizin keyfi olarak değiştirilip değiştirilmeyeceğini size bildirmeyecektir. Kod okurken, ikinci örnek amaç ve işlev açısından çok daha net olacaktır.
Bunun, alıcıların ve belirleyicilerin ilk sırada yer almasının amacını tamamen ortadan kaldıracağı doğru muyum ve doğrulama ve diğer mantıklara (elbette garip yan etkiler olmadan) izin verilmeli mi?
Alıcı ve ayarlayıcılara sahip olmak, "saflık" uğruna kapsülleme değil, sınıfın çağrı koduyla uyumluluğunu bozacak sınıfın arayüzünde bir değişiklik riski olmadan kodun kolayca yeniden yapılandırılmasına izin vermek için kapsülleme ile ilgilidir. Doğrulama, bir ayarlayıcıda tamamen uygun olmakla birlikte, küçük bir risk vardır; arama kodu belirli bir şekilde gerçekleşen doğrulamaya dayanırsa, doğrulamadaki bir değişikliğin arama koduyla uyumluluğu bozması riski vardır. Bu, genellikle nadir görülen ve nispeten düşük riskli bir durumdur, ancak tamamlanma uğruna not edilmelidir.
Doğrulama ne zaman yapılmalı?
Doğrulama, değeri gerçekten ayarlamadan önce ayarlayıcı bağlamında yapılmalıdır. Bu, bir istisna atıldığında, nesnenizin durumunun değişmemesini ve potansiyel olarak verilerini geçersiz kılmamasını sağlar. Genel olarak, doğrulama kodunu ayarlayıcı kodunu nispeten derli toplu bir şekilde tutmak için ayarlayıcı içinde adı verilen ilk şey olacak ayrı bir yönteme devretmek daha iyi olur.
Bir ayarlayıcının değeri değiştirmesine izin verilir mi (belki de geçerli bir değeri bir kanonik içsel gösterime dönüştürebilirsiniz)?
Çok nadir durumlarda, belki. Genel olarak, muhtemelen değil daha iyidir. Bu, başka bir yönteme kalan en iyi şeydir.