Alıcılara izin vermede kesin bir sorun nedir?


15

Ben am aramıyorum semantik hakkında ama sadece makul kullanılan alıcılar sahip gerçek bir engel olan bir durum için bir görüş için. Belki de beni hiç bitmeyen bir sarmal içine atar, belki alternatif daha temizdir ve alıcıları otomatik olarak ele alır, vb. Somut bir şey.

Tüm argümanları duydum, kötü olduklarını duydum çünkü sizi veri kaynağı olarak ele almaya zorlarlar, bir nesnenin "saf durumunu" ihlal ederler "çok fazla verme ama çok kabul et ".

Ama a'nın getDatakötü bir şey olmasının mantıklı bir nedeni yok , aslında, birkaç kişi bunun anlambilim, kendileri için iyi olanlarla ilgili çok şey olduğunu savundu, ama sadece onlara isim vermeyin getX, bana göre, bu en azından komik .

Fikirler olmadan, alıcıları mantıklı bir şekilde kullanırsam ve nesnenin bütünlüğünü ortaya koyarsa açıkça bütünleşmeyen veriler için kırılacak olan bir şey nedir ?

Tabii ki bir şeyi şifrelemek için kullanılan bir dize için alıcıya izin vermek aptal değil, ama ben sisteminizin çalışması gereken verilerden bahsediyorum. Belki veriler aracılığıyla çekilir Providernesneden, ama yine de, nesne hala izin gerekiyor Providerbir yapmak $provider[$object]->getData, etrafında hiçbir yolu yoktur.


Soruyorum Neden: Bana göre, alıcılar, ne zaman makul ve "güvenli" tanrı-gönderilen, benim alıcılar% 99 gibi nesneyi tanımlamak için kullanılır olarak kabul edilir veriler üzerinde kullanılan, ben kod boyunca, sormak Object, what is your name? Object, what is your identifier?, bir nesne ile çalışan herkes bir nesne hakkında bu şeyleri bilmelidir, çünkü programlama ile ilgili hemen hemen her şey kimliktir ve nesnenin kendisinden daha iyi kim bilir? Bu yüzden saflık yapmadığınız sürece gerçek bir sorun göremiyorum.

Ben "neden getters / setters" kötü hakkında tüm StackOverflow sorulara baktım ve seters vakaların% 99 gerçekten kötü olduğunu kabul etsem de, getters sadece onlar kafiye çünkü aynı tedavi gerekmez.

Bir ayarlayıcı, nesnenizin kimliğini tehlikeye atar ve verileri kimin değiştirdiğini hata ayıklamayı çok zorlaştırır, ancak bir alıcı hiçbir şey yapmaz.


2
Benim tavsiyem OO teorisinin çoğunu unutmak. Uygulama. Çok fazla kod yazın ve sonra onu koruyun. Neyin iyi çalıştığı ve aslında bir şey yapmasından ve birkaç ay sonra ona geri dönmekten neyin işe yaramadığı hakkında çok, çok, çok daha fazla şey öğreneceksiniz.
jpmc26

1
@ jpmc26 Annesinde ne .... Aslında hiçbirimizin aslında OOP'u doğru yapmadığını asla fark etmedim, her zaman bir kapsülün alanlarıyla kesinlikle ilgili olan bu kapsülleme fikrine sahip oldum, ancak nesnenin kendisi bir durum ve varlık serbestçe paylaştı. Gerçekten herkes OOP'u yanlış yapıyor, ya da daha doğrusu, paradigma nesneler ise OOP mümkün değildir. OOP'u kesinlikle bir sistemin nasıl çalıştığını ifade etmek için kullanıyorum ve asla kutsal kâse veya SOLID olarak muamele etmiyorum. Onlar sadece çoğunlukla benim kavramımın oldukça iyi açıklanmış (uygulanması yoluyla) tanımlamak için kullandığım araçlardır. Eğer bu doğru ise okumalar var mı?
coolpasta

2
--cont, Ne kadar çok yazdığımda, programlamanın o kadar çok fark ettiğimi, mantıklı olabilmek için gerekli olduğu kadar soyut yapabilmek, başkalarına ve kod tabanınız hakkında size. Tabii ki, bunun teknik tarafı doğru kontrolleri yaptığınızdan / doğru kuralları ayarladığınızdan emin olmaktır. Gerçekte, kim başkalarının kodlarını daha iyi anlamasını sağlamayı başarırsa kazanır. Bunu okuyan herkes için mantıklı olduğundan emin olun, daha sonra nesneleri arayüzler, kontroller ile doğru şekilde bölümlere ayırarak başarısız olmadığından emin olun ve onlarla muhakeme daha kolay olduğunda diğer paradigmalara geçin: esnek olun.
coolpasta

2
Bu bana bir pipet gibi geliyor. Gerçekten kullanılabilir kod yazan herhangi bir ciddi geliştirici getters mantıklı kullanmanın bir sorun olduğunu iddia olacağını inanmıyorum. Soru, alıcıların mantıklı bir şekilde kullanılabileceği anlamına geliyor, bu da alıcıların mantıklı olabileceğini ima ediyor. Alıcıların mantıklı bir kullanımı olmadığını söyleyecek birini mi arıyorsunuz? Bir süre bekleyeceksin.
JimmyJames

2
@coolpasta Haklısın. Saf OOP olup olmadığı gerçekten umrumda değil. Sadece daha iyi. Bana insanlar tarafından anlaşılabilir kırık kod vs çözülemez olan kusursuz CPU sevgi dolu kod arasında bir seçim vermek ve her zaman insan dostu kodu alacak. OOP, SADECE herhangi bir zamanda düşünmem gereken şey sayısını azalttığında faydalıdır. Basit bir prosedürden hoşlanmamın tek nedeni bu. Bu olmadan, beni sebepsiz yere birden fazla kaynak kod dosyası üzerinden atlamama sebep oluyorsunuz.
candied_orange

Yanıtlar:


22

Alıcılar olmadan iyi kod yazamazsınız.

Neden alıcılar kapsülleme kırmak değil, çünkü. Bunun nedeni, alıcıların insanları, üzerinde çalıştıkları verilerle yöntem koymalarını sağlayacak OOP'yi takip etmekten çekinmemeleri değildir. Onlar yapar. Hayır, sınırlar nedeniyle alıcılara ihtiyacınız var.

Kapsülleme ve yöntemlerin üzerinde çalıştıkları verilerle birlikte tutulması fikirleri, sizi bir yöntemi hareket ettirmekten alıkoyan ve böylece verileri taşımaya zorlayan bir sınıra girdiğinizde işe yaramaz.

Gerçekten bu kadar basit. Sınır olmadığında getters kullanıyorsanız gerçek nesneniz olmaz. Her şey usule uygun olmaya başlar. Hangi şimdiye kadar olduğu gibi çalışır.

Gerçek OOP her yere yayabileceğiniz bir şey değildir. Sadece bu sınırlar dahilinde çalışır.

Bu sınırlar çok ince değil. İçlerinde kod var. Bu kod OOP olamaz. İşlevsel de olamaz. Hayır, bu kod bizim ideallerimizi ondan çıkarmaz, böylece sert gerçeklikle başa çıkabilir.

Michael Fetters , portakalın bölümlerini bir arada tutan beyaz bağ dokusundan sonra bu kodu fasya olarak adlandırdı .

Bunu düşünmenin harika bir yolu. Her iki kod türünün de aynı kod tabanına sahip olmasının neden uygun olduğunu açıklar. Bu perspektif olmadan, birçok yeni programcı ideallerine sıkı sıkıya yapışıyor, sonra kalplerini kırıyor ve ilk sınırlarına ulaştıklarında bu ideallerden vazgeçiyorlar.

İdealler sadece uygun yerlerinde çalışırlar. Onlardan vazgeçme, çünkü her yerde çalışmazlar. Onları çalıştıkları yerde kullanın. Bu yer, ön panonun koruduğu sulu kısımdır.

Sınırın basit bir örneği bir koleksiyondur. Bu bir şey tutar ve ne olduğu hakkında hiçbir fikri yoktur. Bir koleksiyon tasarımcısı, ne tutacağına dair hiçbir fikirleri olmadığında, tutulan nesnenin davranış işlevselliğini koleksiyona nasıl taşıyabilir? Yapamazsın. Bir sınıra karşısın. Bu yüzden koleksiyonların alıcıları var.

Şimdi bilseydiniz, bu davranışı taşıyabilir ve durumu taşımaktan kaçınabilirsiniz. Bildiğin zaman yapmalısın. Sen her zaman bilmiyorsun.

Bazı insanlar bunu pragmatik olarak adlandırıyor. Ve budur. Ama neden pragmatik olmamız gerektiğini bilmek güzel.


Anlamsal argümanlar duymak istemediğinizi ve "mantıklı alıcıları" her yere koymayı savunduğunuzu ifade ettiniz. Bu fikrin sorgulanmasını istiyorsun. Bence fikrin onu çerçevelemenizle ilgili sorunları olduğunu gösterebilirim. Ama aynı zamanda nereden geldiğini de biliyorum çünkü oradaydım.

Her yerde alıcı istiyorsanız Python bakın. Özel bir anahtar kelime yok. Yine de Python OOP'u iyi yapıyor. Nasıl? Anlamsal bir numara kullanırlar. Özel olması gereken her şeyi bir alt çizgiyle adlandırırlar. Bunu yapmak için sorumluluk almanız şartıyla onu okuyabilirsiniz. "Hepimiz burada yetişkiniz" diyorlar.

Peki bu ve Java veya C # her şeyi getters arasındaki fark nedir? Üzgünüm ama anlambilim. Pythons altı çizili kongre size çalışanların sadece kapısının arkasına baktığınızı açıkça gösteriyor. Her şeyi tokatlar ve bu sinyali kaybedersiniz. Yansıması ile yine de özel olanı çıkarabilir ve hala semantik sinyali kaybetmemiş olabilirsiniz. Burada yapılması gereken yapısal bir argüman yoktur.

Burada kalan, "sadece çalışanlar" işaretini nereye asacağımıza karar vermektir. Özel olarak nelere dikkat edilmeli? Buna "mantıklı alıcılar" diyorsunuz. Söylediğim gibi, bir alıcı için en iyi gerekçe bizi ideallerimizden uzaklaştıran bir sınırdır. Bu, her şey için alıcılarla sonuçlanmamalıdır. Bir alıcıyla sonuçlandığında, davranışı koruyabileceğiniz sulu bitin içine taşımayı düşünmelisiniz.

Bu ayrım birkaç terime yol açtı. Veri Aktarım Nesnesi veya DTO, hiçbir davranışa sahip değildir. Tek yöntemler getters ve bazen setters, bazen bir kurucu. Bu isim talihsiz çünkü hiç de gerçek bir nesne değil. Alıcılar ve ayarlayıcılar gerçekten sadece bir kesme noktası ayarlamak için bir yer veren kod hata ayıklama. Bu ihtiyaç olmasaydı, sadece kamuya açık alanlar olurdu. C ++ 'da onlara yapı derdik. Bir C ++ sınıfından aldıkları tek fark, varsayılan olarak halka açık olmalarıydı.

DTO'lar iyidir, çünkü onları bir sınır duvarının üzerine atabilir ve diğer yöntemlerinizi güvenli bir şekilde güzel bir sulu davranış nesnesinde tutabilirsiniz. Gerçek bir nesne. İhlal edecek hiçbir alıcı olmadan kapsülleme. Davranış nesnelerim Parametre Nesneleri olarak kullanarak DTO'ları yiyebilir . Bazen paylaşılabilir değişebilir durumu önlemek için defansif bir kopyasını almak zorundayım . Değişken DTO'ları sınırın içindeki sulu kısmın içine yaymıyorum. Onları kapsülledim. Onları saklıyorum. Ve nihayet yeni bir sınıra girdiğimde yeni bir DTO döndürüyorum ve duvardan fırlatıp başka birinin sorunu haline getiriyorum.

Ama siz kimliğinizi ifade eden alıcılar sağlamak istiyorsunuz. Tebrikler, bir sınır buldun. Varlıkların referanslarının ötesine geçen bir kimliği vardır. Yani, bellek adreslerinin ötesinde. Bu yüzden bir yerde saklanmalıdır. Ve bir şey bu şeye kimliğiyle başvurabilmelidir. Kimliği ifade eden bir alıcı son derece makuldür. Varlığın kendisi tarafından verilebileceği kararları almak için o alıcıyı kullanan bir kod yığını değildir.

Sonunda yanlış olan alıcıların varlığı değildir. Kamusal alanlardan çok daha iyi. Kötü olan, Nesne Odaklı olmadığınızı iddia etmek için kullanıldığında. Mektuplar iyidir. Nesneye Yönelik olmak iyidir. Harfler Nesneye Yönelik değildir. Nesneye Dayalı olmak için güvenli bir yer açmak için alıcıları kullanın.


Bu yüzden sordum ve Robert ile konuşmamın görünür olup olmadığından emin değilim, ayrıca "mantıklı alıcıları" kullanmanın beni incittiği özel bir durum bulmaya çalışıyordum. Kendim için ayarlayıcılara katılmıyorum çünkü en azından kendim için, böyle bir eyleme sahip olmak çok zor, her şeyde ayarlayıcıları kullanıyordum ve çok fazla nesne öldürüldüğünde 1 ayarlayıcının bile olduğunu fark ettiğimde ben ... her şeyi yeniden yazmak zorunda kaldım. Çok uzun bir süre boyunca yapılan kapsamlı testlerden sonra, alıcıların mantıklı kullanımı, bir safkan değilseniz, ciddi bir şekilde aşağı tarafı yoktur.
coolpasta

1
@coolpasta veri sahibi nesneleri oluşturabilirsiniz. Veri sahibi nesneleri veri nesneleridir, ancak verilere (açıkça) sahip olacakları şekilde tasarlanır ve adlandırılırlar. Tabii ki bu nesnelerin alıcıları olacak.
rwong

1
@rwong Ne demek istiyorsun clearly? Veriler bana bir şeyden, değerle , açık bir şekilde aktarılırsa , nesnem şimdi verilere sahiptir, ancak anlambilim tarafından, henüz bu noktada, başka birinden verileri almamıştır. Daha sonra, bu verileri dönüştürmek, kendi haline getirmek, verilere dokunduğunuz anda, anlamsal değişiklikler yapmak zorundasınız: olarak adlandırılan verileriniz var $data_from_requestve şimdi üzerinde işlem yaptınız mı? Ad verin $changed_data. Bu verileri başkalarına göstermek ister misiniz? Bir alıcı oluşturun getChangedRequestData, ardından sahiplik açıkça belirlenir. Yoksa öyle mi?
coolpasta

1
"Alıcı olmadan iyi kod yazamazsınız." Bu, sınırların doğal olarak alıcılara ihtiyaç duyduğu düşüncesi gibi, tamamen yanlıştır. Bu pragmatizm değil, sadece tembellik. Sadece çitin üzerine veri atmak ve onunla yapılması, kullanım durumlarını düşünmek ve iyi bir davranışsal api tasarlamak oldukça zordur.
Robert Bräutigam

2
Mükemmel cevap!
cmaster

10

Mektuplar Hollywood Prensibini ihlal ediyor ("Bizi arama, seni arayacağız")

Hollywood Prensibi (diğer bir deyişle İnversiyon Kontrol), işleri halletmek için kütüphane kodunu çağırmamanız gerektiğini belirtir; çerçeve kodunuzu çağırır. Çerçeve bir şeyleri kontrol ettiğinden, iç durumunu müşterilere yayınlamak gerekli değildir. Bilmene gerek yok.

En sinsi haliyle, Hollywood Prensibini ihlal etmek, bir sınıfın durumu hakkında bilgi almak için bir alıcı kullandığınız ve daha sonra elde ettiğiniz değere göre o sınıfa hangi yöntemleri çağıracağınıza karar verdiğiniz anlamına gelir. en iyi şekilde kapsülleme ihlalidir.

Bir alıcı kullanmak , gerçekten ihtiyacınız olmadığında bu değere ihtiyacınız olduğunu ima eder .

Aslında bu performans gelişimine ihtiyacınız olabilir

Mümkün olan maksimum performansa sahip olması gereken aşırı hafif nesnelerde, bir alıcının getirdiği çok küçük performans cezasını ödeyemezsiniz (son derece olası değildir). Bu yüzde 99.9 olmayacak.


1
Bilmeme gerek olmadığını anlıyorum ve gerçeğinle uçacağım . . Ama ihtiyacım olan bir noktaya geldim. Ben Generatortüm Itemsnesneler arasında döngü sonra bir şey daha yapmak için getNameher aramaları bir nesne var Item. Bununla ilgili sorun nedir? Daha sonra, Generatorbiçimlendirilmiş dizeleri tükürür. Bu benim çerçevem ​​dahilinde, bunun için kullanıcıların sağladıkları her şeyi çalıştırmak için kullanabileceği ancak çerçeveye dokunmadan kullanabileceğim bir API'ye sahibim.
coolpasta

3
What is the issue with this?Göremediğim bir şey yok. Aslında bir mapfonksiyon bunu yapar. Ama sorduğunuz soru bu değil. Sen aslında "var mıdır sorulan herhangi bir alıcı tavsiye edilemez olabilir koşullar." Ben iki cevap verdim, ama bu ayarlayıcıları tamamen terk ettiğiniz anlamına gelmiyor.
Robert Harvey

1
Yanlış soruyu soruyorsun. Ben bir pragmatistim; Özel programlarıma en uygun olanı yapıyorum ve amaçlarıma hizmet etmedikçe "ilkelere" fazla stok koymuyorum.
Robert Harvey

2
@ jpmc26: Çerçeveler. Kütüphaneler değil.
Robert Harvey

2
Çerçeve, genel amaçlı bir dili etki alanına özgü bir dile dönüştürme girişimidir. Kütüphane, yeniden kullanılabilir algoritmaların bir koleksiyonudur. Her ikisi de sizden ona güvenmenizi isteyecektir. Bağımlılığı sabit olarak kodlamak veya bağımlılığı kolayca ikame etmek istiyorsanız size kalmış.
candied_orange

2

Getters Sızıntı Uygulama Detayları ve Soyutlamayı Kırma

Düşünmek public int millisecondsSince1970()

Müşterileriniz "ah, bu bir int" düşünecek ve bir olduğunu varsayarak gelen milyarlarca çağrılar olacak int size gerektiğini fark ettiklerinde ... vb tarihleri karşılaştıran tamsayı matematik yapıyor, uzun bir sürü olacak, eski kod sorunları. Bir Java dünyasında, @deprecatedAPI'ye eklersiniz , herkes onu görmezden gelir ve eskimiş, buggy kodunu korumakta kalırsınız. :-( (Diğer dillerin benzer olduğunu varsayıyorum!)

Bu özel durumda, daha iyi bir seçeneğin ne olabileceğinden emin değilim ve @candiedorange yanıtı tamamen yerinde, alıcılara ihtiyacınız olduğunda birçok kez var, ancak bu örnek olumsuzlukları gösteriyor. Her kamu alıcısı sizi belirli bir uygulamaya "kilitleme" eğilimindedir. "Sınırları aşmanız" gerekiyorsa, ancak mümkün olduğunca az, dikkatli ve önceden düşünerek kullanın.


Bu doğrudur, ancak bir veri türünü / yapısını bir nesnenin değişkenine ve bu değişken için alıcıyı kullanan herhangi bir şeye uygulamak için kalıp çözümü nedir?
coolpasta

1
Bu örnek, farklı bir fenomeni, ilkel saplantıyı göstermektedir. Günümüzde çoğu kütüphane ve çerçevenin sırasıyla timepointve sınıflarını temsil eden sınıfları vardır timespan. ( epochbelirli bir değerdir timepoint.) Bu sınıflarda, getIntveya getLongveya gibi alıcılar sağlarlar getDouble. Zamanı manipüle eden sınıflar, (1) zamanla ilgili aritmetikleri bu nesnelere ve yöntemlere devredecekleri ve (2) bu zaman nesnelerine alıcılar aracılığıyla erişim sağlayacak şekilde yazılırsa, sorun alıcılardan kurtulmaya gerek kalmadan çözülür. .
rwong

1
Özetlemek gerekirse, alıcılar API'nın bir parçasıdır ve bu nedenle alıcıların geçmiş, şimdiki ve gelecekteki sonuçlar da dahil olmak üzere tüm sonuçları dikkate alacak şekilde tasarlanması gerekir. Ancak bu, alıcı sayısından kaçınma veya en aza indirme sonucuna yol açmaz. Aslında, bir alıcının atlandığı belirli bir bilgiye erişmeye gelecekte ihtiyaç duyulursa, kütüphane tarafı API değişikliği ve kod değişikliği gerektirecektir. Bu nedenle, belirli bir alıcının uygulanması ya da önlenmesinin gerekip gerekmediğine ilişkin karar, önleyici nedene değil alan adına ve niyete dayanmalıdır.
rwong

1
"millisecondsSince1970" Ocak 1970 sonundan önce 32 bit ints için çalışmayı durdurdu, bu yüzden onu kullanarak çok kod olacak şüpheli :-)
gnasher729

1
@rwong Biraz doğru, ancak zaman noktalarını temsil eden tercih edilen kitaplıkların kararlı olduğunu varsayıyorsunuz. Onlar değil. Örneğin moment.js
user949300

1

Bence ilk anahtar mutlakların her zaman yanlış olduğunu hatırlamaktır.

Sadece kişilerin iletişim bilgilerini saklayan bir adres defteri programı düşünün. Ancak, doğru yapalım ve denetleyici / hizmet / depo katmanlarına ayıralım.

Olacak bir PersonGerçek verileri tutan sınıf : isim, adres, telefon numarası, vb. AddressVe Phonesınıflar da, bu yüzden daha sonra ABD dışındaki şemaları desteklemek için polimorfizmi kullanabiliriz. Bu sınıfların üçü de Veri Aktarım Nesneleri'dir , bu nedenle alıcılar ve ayarlayıcılardan başka bir şey değildirler. Ve, bu mantıklı: Onlar ağır basan ötesinde onlarda bir mantığı var etmeyeceğiz equalsve getHashcode; sizden tam bir kişinin bilgilerini temsil etmelerini istemek mantıklı değil: HTML sunumu, özel bir GUI uygulaması, konsol uygulaması, HTTP uç noktası vb. için mi?

Burada kontrolör, servis ve depo devreye giriyor. Bağımlılık enjeksiyonu sayesinde bu sınıfların hepsi mantık-ağır ve alıcı-hafif olacak.

Kontrolör, enjekte edilecek bir hizmet alacaktır. getsave , her ikisi de bazı makul argümanlar alacak olan (örn., getAda göre arama, posta koduyla arama veya her şeyi alma vesave alacaktır. tek bir Personve kaydedin). Denetleyicide hangi alıcılar olurdu? Somut sınıfın adını elde edebilmek, giriş yapmak için yararlı olabilir, ancak enjekte edilen durumdan başka hangi durumu tutacaktır?

Benzer şekilde, hizmet katmanı bir depoya enjekte edilir, bu yüzden gerçekten alabilir ve devam Personedebilir ve bazı "iş mantığı" olabilir (örneğin, belki de tüm Personnesnelerin en az bir adres veya telefona sahip olmasını isteyeceğiz) numara). Ama yine: bu nesnenin enjekte edilenden başka bir durumu var mı? Yine yok.

Havuz katmanı, işlerin biraz daha ilginç hale geldiği yerdir: bir depolama konumuna bağlantı kuracaktır, örn. bir dosya, bir SQL veritabanı veya bir bellek içi depo. Burada, dosya adını veya SQL bağlantı dizesini almak için bir alıcı eklemek cazip gelebilir, ancak bu sınıfa enjekte edilen durumdur. Havuzun veri deposuna başarılı bir şekilde bağlanıp bağlanmadığını söyleyecek bir alıcısı olmalı mı? Belki, ama bu bilginin depo sınıfının dışında ne faydası var? Depo sınıfının kendisi, gerekiyorsa veri deposuna yeniden bağlanmayı denemelidir; bu, isConnectedözelliğin zaten şüpheli bir değere sahip olduğunu gösterir . Ayrıca, bir isConnectedmülk muhtemelen en doğru olması gerektiğinde yanlış olacaktır: kontrolisConnected veri almayı / depolamayı denemeden önce "gerçek" çağrı yapıldığında havuzun hala bağlanacağını garanti etmez, bu nedenle bir yerde istisna işleme ihtiyacını ortadan kaldırmaz (bunun nereye gideceğine dair argümanlar var, ötesinde bu sorunun kapsamı).

Ayrıca birim testleri de düşünün (birim testleri yazıyorsunuz, değil mi?): Hizmet belirli bir sınıfın enjekte edilmesini beklemez, bunun yerine bir arabirimin somut bir uygulamasının enjekte edilmesini bekler. Bu, uygulamanın bir şey yapmadan veri depolandığı yerde bir değişiklik yapmasına izin vermez, ancak hizmete enjekte edilen depoyu değiştirir. Ayrıca, bir sahte havuz enjekte edilerek hizmetin birim testine izin verir. Bu sınıflardan ziyade arayüzler açısından düşünmek demektir. Havuz arayüzü alıcıları ortaya çıkarabilir mi? Yani, olabilecek herhangi bir iç durum var mı: tüm depolar için ortak, havuzun dışında faydalı ve depoya enjekte edilmemiş mi? Kendimi düşünmeye zorlanıyorum.

TL; DR

Sonuç olarak: tek amacı veri taşımak olan sınıfların yanı sıra, yığındaki başka hiçbir şeyin alıcıyı koyacağı bir yer yoktur: devlet işçi sınıfının dışına enjekte edilir veya ilgisizdir.


Ben bu düşünce hattı C # özelliklerinin doğru kullanımı hakkında tartışma çok benzer buluyorum. Kısacası, mülklerin (yalnızca alıcı veya alıcı-alıcı-çifti olabilecek) belirli bir sözleşmeyi yerine getirmesi beklenir, örneğin "belirlediğiniz şey", "alıcı çoğunlukla yan etkisiz olmalıdır", "Getter hata atmaktan kaçınmalıdır" vb. Sonuçlarınızın aksine, özellikler (veya getters) olarak gösterilmesinde faydalı birçok nesne durumu vardır. Örnekler burada alıntı yapmak için çok fazla.
rwong

2
@rwong Bazı örnekler bilmek isterim, bir ekip tarafından uygulanan "normal" "kurumsal" bir uygulama için diyelim. Ayrıca sadelik adına üçüncü tarafların olmadığını varsayalım. Bilirsiniz, Takvim, Evcil Hayvan dükkanı gibi bağımsız bir sistem, ne istersen.
Robert Bräutigam

1

Fikirler olmadan, alıcıları mantıklı bir şekilde kullanırsam ve nesnenin bütünlüğünü ortaya koyarsa açıkça anlaşılmayan veriler için kırılacak olan bir şey nedir?

Değişken üyeler.

Bir nesnede bir alıcı aracılığıyla ortaya koyduğunuz şeylerden oluşan bir koleksiyonunuz varsa, kendinizi koleksiyona eklenen yanlış şeylerle ilişkili hatalara maruz bırakabilirsiniz.

Bir alıcı aracılığıyla açığa çıkarabileceğiniz değişken bir nesneniz varsa, kendinizi potansiyel olarak nesnenizin iç durumunu beklemediğiniz bir şekilde değiştirmeye açarsınız.

Gerçekten kötü bir örnek, 1'den 100'e kadar sayılan ve Geçerli değerini değiştirilebilir bir referans olarak ortaya koyan bir nesne olabilir. Bu, üçüncü taraf bir nesnenin Current değerini, değerin beklenen sınırların dışında kalacak şekilde değiştirmesine olanak tanır.

Bu çoğunlukla değiştirilebilir nesneleri ortaya koymakla ilgili bir sorundur. Yapıları veya değiştirilemeyen nesneleri ortaya çıkarmak hiç sorun değil, çünkü bunlarda yapılacak herhangi bir değişiklik bunun yerine bir kopyayı değiştirecektir (genellikle bir yapı durumunda örtük bir kopyayla veya değiştirilemez bir nesne durumunda açık bir kopyayla).

Farkı görmeyi kolaylaştırabilecek bir metafor kullanmak.

Bir çiçeğin kendine özgü bazı şeyleri vardır. Bir Colorve bir dizi yaprakları vardır (NumPetals). Eğer o çiçeği gözlemliyorsam, gerçek dünyada rengini açıkça görebiliyorum. Daha sonra bu renge göre kararlar verebilirim. Örneğin, renk siyahsa kız arkadaşına vermeyin ama renk kırmızı ise kız arkadaşına verin. Nesne modelimizde, çiçeğin rengi, çiçek nesnesinde bir alıcı olarak ortaya çıkacaktır. Bu rengi gözlemlemem gerçekleştireceğim eylemler için önemlidir, ancak çiçek nesnesini hiç etkilemez. O çiçeğin rengini değiştirmemeliyim. Aynı şekilde, color özelliğini gizlemek de mantıklı değildir. Bir çiçek genellikle insanların rengini gözlemlemesini engelleyemez.

Çiçeği boyasam, çiçeğin iç kurallarına göre değiştirecek olan ReactToDye (Color dyeColor) yöntemini çağırmalıyım. Sonra Colorözelliği yeniden sorgu ve ReactToDye yöntemi çağrıldıktan sonra herhangi bir değişikliğe tepki verebilir. ColorÇiçeğin doğrudan modifiye edilmesi benim için yanlış olur ve eğer yapabilirsem soyutlama bozulur.

Bazen (daha az sıklıkta, ancak yine de bahsetmeye değer) ayarlayıcılar oldukça geçerli OO tasarımıdır. Bir Müşteri nesnesim varsa, bir ayarlayıcıyı adresleri için göstermek oldukça geçerlidir. İster o ismi setAddress(string address)ya ChangeMyAddressBecauseIMoved(string newAddress)da sadece string Address { get; set; }semantik meselesi. Bu nesnenin iç durumunun değişmesi gerekir ve bunu yapmanın uygun yolu, o nesnenin iç durumunu ayarlamaktır. CustomerYaşadığı adreslerin tarihsel bir kaydına ihtiyacım olsa bile , ayarlayıcıyı iç durumumu uygun şekilde değiştirmek için kullanabilirim. Bu durumda, Customerdeğişmez olması mantıklı değildir ve bir adresi değiştirmenin bunu yapmak için bir ayarlayıcı sağlamaktan daha iyi bir yolu yoktur.

Getters ve setter'lerin kimin kötü olduğunu veya nesne yönelimli paradigmaları kırdığını önermediğinden emin değilim, ancak eğer yaparlarsa, muhtemelen kullandıkları dilin belirli bir dil özelliğine yanıt olarak yapıyorlar. Bunun Java'dan "her şey bir nesne" kültüründen (ve muhtemelen diğer bazı dillere genişlediğinden) büyüdüğünü hissediyorum. .NET dünyasında bu tartışma hiç yoktur. Harfler ve Ayarlayıcılar, yalnızca dilde uygulama yazan kişiler tarafından değil, aynı zamanda dil API'sinin kendisi tarafından kullanılan birinci sınıf bir dil özelliğidir.

Alıcıları kullanırken dikkatli olmalısınız. Yanlış veri parçalarını ifşa etmek istemezsiniz ve verileri yanlış bir şekilde ifşa etmek de istemezsiniz (örn. Değişken nesneler, bir tüketicinin dahili durumu değiştirmesine izin verebilecek yapılara yapılan başvurular). Ancak, nesnelerinizi dış tüketiciler tarafından kullanılabilecek ve aynı tüketiciler tarafından kötüye kullanılmaya karşı korunacak şekilde kapsüllenecek şekilde nesnelerinizi modellemek istersiniz. Genellikle bu alıcılar gerektirir.

Özetlemek gerekirse: Harfler ve Ayarlayıcılar geçerli nesne yönelimli tasarım araçlarıdır. Her uygulama detayının açığa çıkacağı kadar liberal bir şekilde kullanılmazlar, ancak bunları bir nesnenin tüketicileri nesneyi verimli bir şekilde kullanamayacak kadar az kullanmak istemezsiniz.


-1

Fikirleri olmayan, alıcıları kullanırsam kırılacak bir şey nedir ...

Sürdürülebilirlik bozulacaktır.

Herhangi bir zaman (neredeyse her zaman söylemeliyim) temelde sizden istendiğinden daha fazla verdiğiniz bir alıcı sunuyoruz. Bu aynı zamanda istenenden daha fazlasını korumanız gerektiği anlamına gelir, çünkü gerçekliği hiçbir sebep olmadan sürdürülebilirliği azaltmanız gerekir.

@ Candied_orange örneğiyle gidelim Collection. Onun yazdıklarının aksine bir alıcı Collection olmamalıdır . Koleksiyonlar, özellikle tüm öğeler üzerinde yineleme yapmak için çok özel nedenlerle bulunur . O kadar Bu işlevsellik, kimseye bir sürpriz değil gerektiğini uygulanacak Collectionyerine, kullanıcıya bu bariz kullanım senaryosunu iterek ve getters veya etajer-çevrimleri için kullanmak yerine,.

Adil olmak gerekirse, bazı sınırlar yapmak gerek getters. Bu, ne için kullanılacağını gerçekten bilmiyorsanız gerçekleşir. Örneğin Exception, günümüzde Java'nın sınıfından yığın izini programlı olarak alabilirsiniz , çünkü insanlar bunu yazarların öngörmediği veya yapamadığı her türlü meraklı nedenden dolayı kullanmak istediler.


1
Counterexample. İki Collections'yi aynı anda yinelemesi gereken bir işlevi düşünün (A1, B1), (A2, B2), .... Bunun için bir "zip" uygulaması gerekir. Yineleme işlevi ikisinden birinde uygulandığında "zip" i nasıl uygularsınız - diğerinde Collectionkarşılık gelen öğeye nasıl erişirsiniz?
rwong

@rwong Kütüphanenin nasıl yazıldığına bağlı olarak kendisi ile Collectionuygulama zipyapmak zorundadır. Yoksa, onu uygular ve kütüphane oluşturucuya bir çekme isteği gönderirsiniz. Bazı sınırların bazen alıcılara ihtiyaç duyduğunu kabul ettim, asıl sorunum alıcıların bugünlerde her yerde olması.
Robert Bräutigam

Bu durumda, kütüphanenin Collectionen azından kendi uygulaması için nesne üzerinde alıcılara sahip olması gerektiği anlamına gelir zip. (Yani, alıcı en azından paket görünürlüğüne sahip olmalıdır.) Ve şimdi çekme talebinizi kabul eden kütüphane yaratıcısına güveniyorsunuz ...
1919'da

Seni tam olarak anlamıyorum. CollectionAçıkçası kendi iç durumunu erişebilir veya herhangi daha doğrusu Collectionörneği en başka iç durumu erişebilirler. Aynı tip, alıcıya gerek yok.
Robert Bräutigam

Ben de seni duyuyorum, ama yine de, alıcılar için en iyi çözüm tam olarak nedir? Sorunun kapsamı dışında olduğunu biliyorum.
coolpasta
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.