Getters'da Ne Kadar Mantık


46

İş arkadaşlarım bana alıcılarda ve ayarlayıcılarda mümkün olduğunca az mantık olması gerektiğini söyledi.

Bununla birlikte, kullanıcıları / programcıları uygulama detaylarından korumak için alıcılar ve ayarlayıcılarda birçok şeyin gizlenebileceğine inanıyorum.

Yaptıklarımın bir örneği:

public List<Stuff> getStuff()
{
   if (stuff == null || cacheInvalid())
   {
       stuff = getStuffFromDatabase();
   }
   return stuff;
}

İşin bana bir şeyler yapmamı söylediğinin bir örneği (Bob Amca'dan 'Temiz Kod' diyorlar):

public List<Stuff> getStuff()
{
    return stuff;
}

public void loadStuff()
{
    stuff = getStuffFromDatabase();
}

Bir ayarlayıcı / alıcıda ne kadar mantık uygundur? Veri saklamanın ihlali dışında boş alıcı ve ayarlayıcıların kullanımı nedir?


6
Bu daha çok tryGetStuff () bana benziyor ...
Bill Michell

16
Bu bir 'alıcı' değildir. Bu terim, yanlışlıkla bir 'get' adını girdiğiniz bir yöntem değil, bir mülkün okuma erişimcisi için kullanılır.
Boris Yankov

6
İkinci örneğin, bahsettiğiniz bu temiz kod kitabının adil bir örneği mi, yoksa birisinin bu konudaki yanlış sonunu aldığını mı bilmiyorum, ama kırılganlığı bozmayan bir şey temiz koddur.
Jon Hanna

@ BorisYankov Peki ... ikinci yöntem. public List<Stuff> getStuff() { return stuff; }
R. Schmitz

Tam kullanım durumuna bağlı olarak, önbelleğimi ayrı bir sınıfa ayırmayı seviyorum. Bir StuffGetterarayüz yapın, StuffComputerhesaplamaları yapın ve cache'ye StuffCachererişmekten veya çağrıları sarmalanmasına yönlendirmekten sorumlu olan bir nesnenin içine sarın StuffComputer.
Alexander,

Yanıtlar:


71

İşin sana bir şeyler yapmanı söyleme şekli topal.

Genel bir kural olarak, işleri yapma yöntemim şu şekildedir: eğer eşyaları almak hesaplamalı olarak ucuzsa, (ya da çoğu şans önbellekte bulunursa), o zaman getStuff () stiliniz iyi olur. Maddelerin elde edilmesinin hesaplama açısından pahalı olduğu biliniyorsa, bu yüzden pahalı olması, arayüzde maliyetinin reklamını yapmak için çok gerekliyse, o zaman bunu getStuff () olarak adlandırmazdım, belirtmek için onu hesaplamakStuff () veya benzeri bir şey olarak adlandırırım. yapılacak bazı işler olacak.

Her iki durumda da, işin size bir şeyler yapmasını söyleme şekli topaldır, çünkü loadStuff () önceden çağrılmadıysa, getStuff () patlar, bu nedenle işlem sırası karmaşıklığını getirerek arabiriminizi karmaşıklaştırmanızı isterler. ona. Operasyon sırası, aklıma gelen en kötü karmaşıklıktır.


23
İşlem sırası karmaşıklığından bahsetmek için +1. Geçici bir çözüm olarak, belki çalışma benden her zaman loadStuff () yapıcısını çağırmamı isteyecektir, ancak bu her zaman yüklenmek zorunda kalacağı için de kötü olacaktır. İlk örnekte, veriler yalnızca gerektiğinde tembel olarak yüklenir; bu, olabildiğince iyi.
laurent

6
Genellikle "gerçekten ucuzsa, bir özellik alıcı kullanın. Pahalıysa, bir işlev kullanın" kuralını uygularım. Bu genellikle bana iyi hizmet eder ve vurguladığınız gibi uygun şekilde adlandırmak da benim için de iyi görünüyor.
Denis Troller

3
başarısız olursa - bu bir alıcı değil. Bu durumda ya DB bağlantısı kapalıysa?
Martin Beckett

6
+1, kaç tane yanlış cevap gönderildiğine biraz şok oldum. Uygulama detaylarını gizlemek için Alıcılar / Belirleyiciler mevcuttur, aksi takdirde değişken sadece herkese açık hale getirilmelidir.
Izkata

2
Unutmayınız ki, loadStuff()fonksiyondan önce fonksiyonun çağrılması getStuff(), sınıfın kaputun altında neler olup bittiğinden tam olarak uzaklaşmadığı anlamına gelir.
rjzii

23

Alıcıların mantığı tamamen iyi.

Ancak bir veritabanından veri almak, "mantık" dan çok daha fazlasıdır. Pek çok şeyin yanlış gidebileceği ve deterministik olmayan bir şekilde çok pahalı operasyonlar dizisi içerir . Bunu bir alıcıda dolaylı olarak yapmaktan çekinirim.

Öte yandan, ORM'lerin çoğu koleksiyonların tembel yüklenmesini desteklemektedir, bu temelde tam olarak ne yaptığınızdır.


18

'Temiz Kod'a göre, mümkün olduğu kadar bölünmüş olması gerektiğini düşünüyorum.

public List<Stuff> getStuff() {
   if (hasStuff()) {
       return stuff;
   }
   loadStuff();
   return stuff;
}

private boolean hasStuff() {
    if (stuff == null) {
       return false;
    }
    if (cacheInvalid()) {
       return false;        
    }
    return true;
} 

private void loadStuff() {
    stuff = getStuffFromDatabase();
}

Elbette, yazdığınız güzel biçimin, bir bakışta herkesin anlayabileceği bir kod bölümü ile doğru olanı yapması koşuluyla, bu tamamen saçmalıktır:

public List<Stuff> getStuff() {
   if (stuff == null || cacheInvalid()) {
       stuff = getStuffFromDatabase();
   }
   return stuff;
}

Eşyaların kaputun altına nasıl girildiği, arayanın baş ağrısı olmamalı ve özellikle bazı şeyleri keyfi bir şekilde "doğru sırayla" çağırmayı hatırlamak, arayanın baş ağrısı olmamalıdır.


8
-1. Asıl baş ağrısı, arayan kişi takıldığında, basit bir alıcı çağrısının neden cehennem gibi yavaş bir veritabanı erişimi ile sonuçlandığını anlamaya başlamasından kaynaklanacak.
Domenic

14
@Domenic: Yine de veritabanı erişiminin yapılması gerekiyor, kimsenin performansını yapmadan tasarruf etmiyorsunuz. Buna ihtiyacın olursa List<Stuff>, almanın tek yolu var.
DeadMG

4
@lukas: Teşekkürler, önemsiz kod bitlerini bir satır daha uzun yapmak için 'Temiz' Kodunda kullanılan tüm püf noktaları hatırlamıyordum ;-) Şimdi düzeltildi.
Joonas Pulakka

2
Robert Martin'e iftira atıyorsun. Asla basit bir boolean kavuşmasını dokuz satır işlevine genişletmez. İşleviniz hasStufftemiz kodun tam tersi.
kevin cline

2
Bu cevabın başlangıcını okudum ve “başka bir kitap tapanın var” diye düşünerek onu geçeceğim ve sonra “Tabii ki bu tamamen saçmalık” kısmı gözüme çarptı. İyi dedi! C -: =
Mike Nakis

8

Bana alıcılarda ve ayarlayıcılarda mümkün olduğunca az mantık olması gerektiğini söylediler.

Sınıfın ihtiyaçlarını karşılamak için gereken kadar mantık olması gerekiyor. Kişisel tercihim mümkün olduğunca az, ancak kodu korurken, genellikle orijinal alıcıyı mevcut alıcılarla / ayarlayıcılarla bırakmanız gerekir, ancak yeni iş mantığını düzeltmek için bunlara çok fazla mantık koymanız gerekir (örneğin, "müşteriler" "911 sonrası bir ortamda bulunan alıcı," müşterinizi tanıyın "ve OFAC düzenlemeleri ile bir araya gelmeli , bazı ülkelerden gelen müşterilerin (Küba veya İran gibi) görünmesini yasaklayan bir şirket politikasıyla bir araya geldi.

Örnekte, ben de seninkini tercih ve "amca bob" sürüm aramaya hatırlamak kullanıcılar / bakıcılarına gerektirdiğinden "amca bob" örnek sevmediğim loadStuff()onlar aramadan önce getStuff()- bu felakete davetiye olup olmadığını sürdürücüler unutuyor herhangi bir tek bir (veya daha da kötüsü, asla bilmiyordum). Son on yılda çalıştığım yerlerin çoğu hala on yıldan daha eski olan kodları kullanıyor, bu nedenle bakım kolaylığı göz önünde bulundurulması gereken önemli bir faktör.


6

Haklısın, meslektaşların yanlış.

Bir get metodunun yapması gereken veya yapmaması gerekenler hakkında herkesin kurallarını unutun. Bir sınıf bir şeyin soyutlamasını sunmalıdır. Sınıfınız okunabilir stuff. Java'da, özellikleri okumak için 'get' yöntemlerini kullanmak gelenekseldir. Milyarlarca çizgi çerçevenin, stuffarayarak okunmasını bekledikleri yazılmıştır getStuff. İşlevinize fetchStuffveya başka bir şeye ad verirseniz getStuff, sınıfınız tüm bu çerçevelerle uyumsuz olacaktır.

Onları Hazırda Beklet'e yönlendirebilir, burada 'getStuff ()' çok karmaşık şeyler yapabilir ve başarısızlığa RuntimeException'ı atar.


Hazırda Bekletme bir ORM'dir, bu nedenle paketin kendisi niyetini ifade eder. Paketin kendisi bir ORM değilse, bu amaç kolayca anlaşılmaz.
FMJaguar

@ FMJaguar: kolayca kolayca anlaşılabilir. Hazırda Bekletme, bir nesne ağı sunmak için veritabanı işlemlerini özetler. OP adlı bir özelliğe sahip bir nesneyi sunmak için bir veritabanı işlemi özetliyor stuff. Her ikisi de arama kodunu yazmayı kolaylaştırmak için ayrıntıları gizler.
kevin cline

Bu sınıf bir ORM sınıfı ise, niyet diğer bağlamlarda zaten ifade edilir: soru kalır: "Başka bir programcı alıcıyı çağırmanın yan etkilerini nasıl biliyor?". Program 1k sınıfları ve 10k alıcıları içeriyorsa, bunlardan herhangi birinde veritabanı çağrıları yapılmasına izin veren bir politika sorun olabilir
FMJaguar

4

Bunun gibi sesler, işlev adlarını nasıl kontrol etmeyi tercih ettiğinizden etkilenebilecek, uygulamalara karşı biraz daha saf olabilir. Uygulanan bakış açısıyla, daha çok görmek isterdim:

List<String> names = clientRoster.getNames();
List<String> emails = clientRoster.getEmails();

Aksine:

myObject.load();
List<String> names = clientRoster.getNames();
List<String> emails = clientRoster.getEmails();

Veya daha da kötüsü:

myObject.loadNames();
List<String> names = clientRoster.getNames();
myOjbect.loadEmails();
List<String> emails = clientRoster.getEmails();

Bu sadece diğer kodları daha fazla gereksiz hale getirme ve okumayı zorlaştırmaya meyillidir, çünkü tüm benzer çağrılara girmeye başlamanız gerekir. Ek olarak, yükleyici işlevlerini veya benzerlerini çağırmak, birlikte çalıştığınız nesnenin uygulama ayrıntılarından artık soyutlanmamak için OOP'yi kullanmanın tüm amacını ortadan kaldırır. Bir clientRosternesneniz varsa, nasıl getNamesçalıştığını umursamanız gerekmiyor , tıpkı bir aramanız loadNamesgerektiği gibi, müşterilerin isimlerini getNamessize verdiğini bilmelisiniz List<String>.

Bu nedenle, mesele anlamsallık ve verinin elde edilmesi için en iyi isim hakkında daha çok şey gibi geliyor. Eğer şirket (ve diğerleri) getve setön ekiyle ilgili bir sorun yaşarsa, retrieveNamesbunun yerine işlevi çağırmak ister misiniz ? Neler olduğunu söylüyor, ancak işlemin bir getyöntemden beklenebileceği gibi anında olacağı anlamına gelmiyor .

Bir erişimci yöntemindeki mantık açısından, değişkenle birlikte meydana gelen yalnızca nominal etkileşimle, anında olduğu gibi, minimumda tutunuz. Bununla birlikte, bu genellikle yalnızca basit tipler için de geçerlidir, karmaşık veri tipleri (yani List) bir mülkte düzgün bir şekilde kapsüllenmesi daha zor buluyorum ve genellikle katı bir mutasyona ve erişimciye karşı onlarla etkileşime geçmek için başka yöntemler kullanıyorum.


2

Bir alıcıyı çağırmak, bir alanı okumakla aynı davranışı sergilemelidir:

  • Değeri almak ucuz olmalı
  • Setter ile bir değer ayarladıysanız ve ardından alıcı ile okuduysanız, değer aynı olmalıdır
  • Değeri almanın hiçbir yan etkisi olmamalıdır
  • Bir istisna atmamalı

2
Bu konuda tamamen aynı fikirde değilim. Yan etkisi olmaması gerektiğine katılıyorum, ancak onu alandan farklı kılacak şekilde uygulamanın tamamen iyi olduğunu düşünüyorum. .NET BCL'ye bakıldığında InvalidOperationException alıcılara bakarken yaygın olarak kullanılır. Ayrıca, işlem sırası ile ilgili MikeNakis'in cevabına bakınız.
Maksimum

Sonuncusu hariç tüm puanları kabul et. Bir değer elde etmenin bir hesaplama yapmayı veya ayarlanmamış olabilecek diğer değerlere veya kaynaklara bağlı başka bir işlemi yapmayı içerebileceği kesinlikle mümkündür. Bu durumlarda alıcının bir tür istisna atmasını beklerdim.
TMN

1
@TMN: En iyi senaryoda, sınıf, alıcıların istisna yapabilen işlemleri yapmaları gerekmeyecek şekilde düzenlenmelidir . İstisnalara yol açabilecek yerlerin en aza indirilmesi, beklenmedik sürprizlerin azalmasına neden olur.
hugomg

8
Belirli bir örnekle ikinci noktaya katılmıyorum gidiyorum: foo.setAngle(361); bar = foo.getAngle(). barolabilir 361, ancak 1açılar bir aralığa bağlıysa meşru olarak da olabilir .
zzzzBov

1
-1. (1) olup , bu örnekte, ucuz - yavaş yüklemeden sonra. (2) şu anda örnekte hayır "setter" var, ama biri ardına ve sadece setleri eklerse stuff, alıcı olacak aynı değeri döndürür. (3) Örnekte gösterildiği gibi tembel yükleme "görünür" yan etkiler üretmez. (4) sonradan "tembel yükleme" tanıtan beri tartışmalıdır, belki geçerli bir nokta, olabilir eski API sözleşme değiştirmek - ama bir karar vermek için bu sözleşme bakmak zorundadır.
Doktor Brown

2

Kendi değerini hesaplamak için diğer özellikleri ve yöntemleri çağıran bir alıcı da bir bağımlılık anlamına gelir. Örneğin, mülkünüzün kendisini hesaplayabilmesi ve bunu yapmak için başka bir üye kurulmasını gerektiriyorsa, mülkünüze tüm üyelerin zorunlu olarak ayarlanmadığı durumlarda başlatma kodunda erişilirse, yanlışlıkla boş referanslar için endişelenmeniz gerekir.

Bu, 'alıcıdaki mülkleri destekleme alanı olmayan başka bir üyeye asla erişmemek' anlamına gelmez, bu yalnızca nesnenin gereken durumunun ne olduğunu ima ettiğinize dikkat etmek anlamına gelir ve bu beklediğiniz bağlamla eşleşiyorsa erişilecek bu özelliğe.

Ancak, verdiğiniz iki somut örnekte, birini diğerinden seçmemin nedeni tamamen farklı. Alıcınız ilk erişimde başlatılır, örneğin, Tembel Başlatma . İkinci örneğin bir önceki noktada başlatıldığı varsayılmaktadır, örneğin, Açık Başlatma .

Tam olarak başlatıldığında, önemli olabilir veya olmayabilir.

Örneğin, çok çok yavaş olabilir ve kullanıcının, erişimi ilk tetiklediğinde beklenmedik şekilde hıçkırmak yerine performanstan ziyade, kullanıcının bir gecikme beklediği bir yükleme adımı sırasında yapılması gerekir (örneğin, kullanıcı sağ tıklar, bağlam menüsü görünür, kullanıcı zaten sağ tıkladım).

Ayrıca, bazen, önbelleğe alınmış özellik değerini etkileyebilecek / kirletebilecek her şeyin gerçekleştiği uygulamada bariz bir nokta vardır. Daha sonra bağımlılıkların hiçbirinin değişmediğini ve istisnalar atamadığını bile doğrulayabilirsiniz. Bu durumda, kodlama işlemini daha karmaşık ve zihinsel olarak takip etmeyi zorlaştırmaktan kaçınmak için, özellikle hesaplanması pahalı olmasa da, bu noktada değeri önbelleğe almak mantıklıdır.

Bununla birlikte, Lazy Initialization, birçok başka durumda çok anlamlı. Bu nedenle, sık sık programlamada bir kurala indirgemenin zorluğunu programlamada olduğu gibi, somut koda gelir.


0

Sadece, @NikeNakis'in dediği gibi yapın ... Eğer sadece eşyaları alırsanız sorun değil ... Başka bir şey yaparsanız, işi yapan ve herkese açık hale getiren yeni bir fonksiyon yaratın.

Mülkünüz / işleviniz yalnızca adının yazdığı şeyi yapıyorsa, geriye kalan komplikasyon için fazla yer kalmaz. Uyum IMO anahtarıdır


1
Buna dikkat edin, içsel durumunuzun çok fazla açığa çıkmasına neden olabilirsiniz. Sen boş bir sürü rüzgar istemiyorum loadFoo()ya preloadDummyReferences()ya createDefaultValuesForUninitializedFields()da sınıfın ilk uygulama onlara ihtiyaç sırf yöntemlerle.
TMN

Tabii ki ... Sadece isminin ne olduğunu söylersen çok fazla sorun olmaması gerektiğini söylüyordum ... ama söylediğin kesinlikle doğru ...
Ivan Crojach Karačić

0

Şahsen, Stuff öğesinin yapıcısındaki bir parametre aracılığıyla gereksinimini ortaya koyardım ve hangi sınıfın hangi nesneyi somutlaştırdığını, nereden geleceğini bulmak için çalışmasını sağlardım. İşler boşsa boş döndürmelidir. OP'nin orijinali gibi akıllı çözümler denememeyi tercih ederim, çünkü uygulamanızın içindeki böcekleri gizlemenin kolay bir yolu çünkü bir şey kırıldığında neyin yanlış olabileceği belli değil.


0

Burada sadece "uygunluk" yerine daha önemli konular var ve kararınızı bunlara dayandırmalısınız . Esas olarak, buradaki büyük karar, insanları önbelleği atlatmak için izinsiz bırakmak isteyip istemediğinizdir.

  1. İlk önce, kodunuzu yeniden düzenlemenin bir yolu olup olmadığını düşünün, böylece tüm gerekli yük çağrıları ve önbellek yönetimi yapıcı / başlatıcıda yapılır. Bu mümkünse, değişmeyen kısmı 2. kısımdaki basit alıcıya yapmanıza izin veren bir sınıf oluşturabilirsiniz. 1. kısımdaki karmaşık alıcıların güvenliği ile. (Bir kazan-kazan senaryosu)

  2. Eğer böyle bir sınıf oluşturamazsanız, bir takas durumunuz olup olmadığına karar verin ve tüketicinin önbellek kontrol kodunu atlamasına izin vermek isteyip istemediğinize karar vermeniz gerekir.

    1. Tüketicinin önbellek kontrolünü asla atlamaması ve performans cezalarına aldırış etmemeniz önemliyse, o zaman çeki alıcının içinde birleştirin ve tüketicinin yanlış şeyi yapmasını imkansız hale getirin.

    2. Önbellek kontrolünü atlamak uygunsa ya da alıcıdaki O (1) performansı garantilemeniz çok önemliyse, ayrı çağrılar kullanın.

Daha önce de belirtmiş olabileceğiniz gibi, “temiz kod” un “her şeyi küçük fonksiyonlara bölme” felsefesinin büyük bir hayranı değilim. Herhangi bir sırayla çağrılabilen bir grup ortogonal fonksiyonunuz varsa, bunları ayırmak size düşük maliyetle daha etkileyici bir güç verecektir. Bununla birlikte, işlevleriniz düzen bağımlılıklarına sahipse (veya yalnızca belirli bir düzende gerçekten faydalıysa), bunları bölmek yalnızca çok az fayda eklerken yanlış şeyler yapmanın yollarını artırır.


-1, yapıcılar başlatmalı, yapmalı. Bir yapıcıya veritabanı mantığı koymak, bu sınıfı tamamen test edilemez kılar ve bunlardan bir avuçtan fazlasına sahipseniz, uygulama başlatma zamanınız büyük olacaktır. Ve bu sadece yeni başlayanlar için.
Domenic

@Domenic: Bu anlamsal ve dile bağlı bir konudur. Bir nesnenin kullanıma uygun olduğu ve uygun değişmezleri sağladığı ve yalnızca sonradan tamamen inşa edildiği nokta.
hugomg

0

Kanımca, Getters’in içinde çok fazla mantık olmamalı. Yan etkileri olmamalıdır ve onlardan asla bir istisna almamalısınız. Tabii ki ne yaptığını bilmiyorsun. Alıcılarımın çoğunda içlerinde mantık yok ve sadece bir tarlaya git. Ancak bunun kayda değer istisnası, kullanımı mümkün olduğu kadar basit olması gereken genel bir API ile oldu. Bu yüzden, başka bir alıcı aranmazsa başarısız olabilecek bir alıcı buldum. Çözüm? var throwaway=MyGetter;Ona bağlı alıcıda olduğu gibi bir kod satırı . Gurur duymuyorum ama hala daha temiz bir yol göremiyorum


0

Bu tembel yükleme ile önbellekten bir okuma gibi görünüyor. Diğerlerinin de belirttiği gibi, kontrol ve yükleme diğer yöntemlere ait olabilir. Yüklemenin senkronize edilmesi gerekebilir, böylece aynı anda yirmi adet iş parçacığı yüklenmez.

getCachedStuff()Sabit bir yürütme süresine sahip olmayacağından alıcı için bir ad kullanmak uygun olabilir .

Rutinin nasıl cacheInvalid()çalıştığına bağlı olarak , null kontrolü gerekli olmayabilir. stuffVeritabanından doldurulmadığı sürece önbelleğin geçerli olmasını beklemem .


0

Liste döndüren alıcılarda görmeyi beklediğim ana mantık, listenin değiştirilemez olduğundan emin olmak için mantıktır. Her iki örneğinizin yanında olduğu gibi, potansiyel olarak kapsülleme kırılır.

gibi bir şey:

public List<Stuff> getStuff()
{
    return Collections.unmodifiableList(stuff);
}

Alıcıda önbelleklemeye gelince, bunun iyi olacağını düşünüyorum ancak önbellek oluşturma işlemi önemli bir zaman aldıysa önbellek mantığını kaldırmak için cazip gelebilirim. yani bağlıdır.


0

Tam kullanım durumuna bağlı olarak, önbelleğimi ayrı bir sınıfa ayırmayı seviyorum. Bir StuffGetterarayüz yapın, StuffComputerhesaplamaları yapın ve cache'ye StuffCachererişmekten veya çağrıları sarmalanmasına yönlendirmekten sorumlu olan bir nesnenin içine sarın StuffComputer.

interface StuffGetter {
     public List<Stuff> getStuff();
}

class StuffComputer implements StuffGetter {
     public List<Stuff> getStuff() {
         getStuffFromDatabase()
     }
}

class StuffCacher implements StuffGetter {
     private stuffComputer; // DI this
     private Cache<List<Stuff>> cache = new Cache<>();

     public List<Stuff> getStuff() {
         if cache.hasStuff() {
             return cache.getStuff();
         }

         List<Stuffs> stuffs = stuffComputer.getStuff();
         cache.store(stuffs);
         return stuffs;
     }
}

Bu tasarım, kolayca önbellek eklemenizi, önbelleği kaldırmanızı, altta yatan türev mantığını değiştirmenizi sağlar (örneğin, sahte veriyi geri döndüren DB'ye erişme), vb.


-1

IMHO, bir tasarım sözleşmeli kullanırsanız çok basittir. Alıcınızın neyi sağlaması gerektiğine karar verin ve buna göre sadece kod verin (basit kod veya bir yere dahil olabilecek veya yetki verilmiş olan bazı karmaşık mantık).


+1: Sana katılıyorum! Nesnenin yalnızca bazı verileri tutması gerekiyorsa, alıcılar yalnızca nesnenin geçerli içeriğini döndürmelidir. Bu durumda, verileri yüklemek başka bir nesnenin sorumluluğundadır. Sözleşme, nesnenin bir veritabanı kaydının proxy'si olduğunu söylüyorsa, alıcı anında verileri almalıdır. Veriler yüklendiyse daha güncel hale gelebilir ancak güncel değilse: nesneye veritabanındaki değişikliklerden haberdar edilmeli mi? Bence bu soruya benzersiz bir cevap yok.
Giorgio
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.