Buna "kesişen endişeler" adı verilen, SOLID / DI / IoC'yi kırmak için geçerli bir bahane mi?


43

Meslektaşlarım "günlüğe kaydetme / önbellekleme / vb." Kesişen bir endişedir "demeyi sever ve ardından her yerde karşılık gelen singleton'u kullanmaya devam eder. Yine de IoC ve DI'yi seviyorlar.

SOLI D ilkesini kırmak gerçekten geçerli bir bahane mi?


27
SOLID ilkelerinin çoğunlukla sadece bilmeden onları zaten bilmeden takip etmek için gerekli deneyime sahip olanlar için yararlı olduğunu buldum.
svidgen

1
"Kesişen kaygı" terimini oldukça spesifik bir terim (yönlere bağlı) ve mutlaka singleton ile eşanlamlı olmadığına öğrendim. Kayıt işlemi, genel bir mesajı aynı anda birden fazla yere aynı anda kaydetmek istediğinizde (örneğin, her aramayı, aramayı yapan bir servis yöntemine veya başka bir denetim türü günlüğüne kaydetmeye devam etmek istemeniz) anlamında çapraz kesilen bir kaygı olabilir. Ancak, logging'in (genel anlamda), her yerde kullanıldığı için kesişen bir endişe olmadığını savunuyorum. Bu gerçekten standart bir terim olmasa da, bunun her zaman "her yerde kaygı verici" olduğunu düşünüyorum.
Pace

4
@svidgen, SOLID ilkeleri, tanımadıklarını kodunuzu gözden geçirip neden bu şekilde yaptığınızı sorduğunda da kullanışlıdır. Bir prensibi işaret edip "bu yüzden"
diyebilmek çok güzel

1
Günlüğe kaydetmenin neden özel bir durum olduğunu düşünüyorsunuz? Bazı verileri, genellikle kullandığınız X çerçevesinin bir parçası olarak yönlendirmek oldukça basit bir kanaldır.
ksiimson,

Yanıtlar:


42

Hayır.

SOLID, kaçınılmaz değişiklikleri hesaba katan kılavuzlar olarak mevcuttur. Eğer Are gerçekten ... senin günlüğü kütüphane veya hedef değişecek, ya süzme veya biçimlendirme veya hiçbir zaman? Eğer Are gerçekten ... senin önbelleğe alma kitaplık veya hedefi veya strateji veya kapsam belirleme veya değişmeyecek?

Tabiki öylesin. En azından , bunları test etmek için izole etmek için aklı başında bir şekilde alay etmek isteyeceksiniz. Ve onları test etmek için izole etmek isteyecekseniz, muhtemelen onları gerçek hayattaki nedenlerden izole etmek istediğiniz bir ticari nedenle karşılaşırsınız.

Ve daha sonra, kaydedicinin kendisinin değişikliği ele alacağı argümanını elde edersiniz . "Ah, hedef / filtreleme / biçimlendirme / strateji değişirse, o zaman sadece config'u değiştiririz!" Bu çöp. Artık sadece bunların hepsini işleyen bir Tanrı Nesnesine sahip değilsiniz, kodunuzu XML (veya benzer) bir şekilde yazıyorsunuz, statik analiz yapmıyorsunuz, derleme zamanı hataları almıyorsunuz ve Gerçekten etkili birim testleri almazsınız.

SOLID kurallarını ihlal eden durumlar var mı? Kesinlikle. Bazen işler olmaz (zaten tam yeniden yazma gerektirmeden) değiştirin. Bazen hafif bir LSP ihlali en temiz çözümdür. Bazen izole edilmiş bir arayüz oluşturmak hiçbir değer sağlamaz.

Ancak günlüğe kaydetme ve önbelleğe alma (ve diğer her yerde bulunan çapraz kesilen kaygılar) bu durumlar değildir. Genelde yönergeleri görmezden geldiğinizde aldığınız kaplin ve tasarım problemlerinin harika örnekleridir.


22
O zaman ne alternatifin var? Yazdığın her sınıfa bir ILogger enjekte etmek mi? Kaydedici gerektiren her sınıf için bir dekoratör yazmak?
Robert Harvey,

16
Evet. Bir şey bir bağımlılık ise , onu bir bağımlılık yapın . Ve eğer bu çok fazla bağımlılık anlamına geliyorsa veya bir kayıt cihazını gitmemesi gereken bir yere geçiriyorsanız - iyi , şimdi tasarımınızı düzeltebilirsiniz.
Telastyn


20
Ben dogmatik IoC ile olan asıl mesele hemen hemen olmasıdır tüm çağdaş kod bağlıdır şey ne uzak enjekte ne de mı alınıyor. C #, örneğin, sık sık soyut gitmiyorsun yazarsanız Stringveya Int32hatta Listdışarı modülünün. Değişimin planlanmasının makul ve mantıklı olduğu bir nokta var . Ve en belirgin "çekirdek" türlerin ötesinde, muhtemelen neyin değişebileceğini ayırt etmek gerçekten sadece bir deneyim ve yargı meselesidir.
svidgen

6
@svidgen - Umarım dogmatik IoC'yi savunan olarak cevabımı okumamışsındır. Ve sadece, bu temel türleri (ve ihtiyatlı olan diğer şeyleri) soyutlamadığımız için global bir List / String / Int / etc'ye sahip olmanın tamam olduğu anlamına gelmez.
Telastyn

38

Evet

Bu, "çapraz kesim kaygısı" teriminin tam anlamıdır - bu, SOLID ilkesine tam olarak uymayan bir şey anlamına gelir.

İdealizmin gerçeklikle buluştuğu yer burasıdır.

SOLID'e yeni başlayan ve kesişen insanlar genellikle bu zihinsel zorlukla karşı karşıya kalıyor. Sorun değil, çıldırma. Her şeyi SOLID'in şartlarına sokmaya çalışın, ancak SOLID'in mantıklı olmadığı yerlerde kayıt ve önbellekleme gibi birkaç yer var. Kesişmek SOLID'in kardeşidir, el ele giderler.


9
Gerekçeli, pratik, dogmatik olmayan bir cevap.
user1936,

11
Lütfen neden beş SOLID ilkesinin hepsinin birbiriyle kesişen kaygılardan ihlal edildiğini söyleyebilir misiniz? Bunu anlamak için problemlerim var.
Doktor Brown

4
Evet. Potansiyel olarak her bir prensibi “kırmak” için iyi bir sebep düşünebilirim; ama 5'ini kırmak için tek bir sebep değil!
svidgen

1
Bir ünite testi için bir singleton logger / önbellekle alay etmem gerektiğinde kafamı duvara çarpmama gerekmemek benim için ideal olurdu. Bir web uygulamasını bir test olmadan yapmanın nasıl bir şey olduğunu bir düşünün HttpContextBase(tam olarak bu nedenle tanıtıldı). Bu sınıf olmadan gerçekliğimin gerçekten ekşi olacağından eminim.
devnull

2
@ devir, belki çapraz mesele kendilerini ilgilendirmek yerine, mesele budur ...
Örümcek Boris

25

Günlük için bence. Günlük kaydı yaygındır ve genellikle hizmet işlevselliği ile ilgisi yoktur. Günlük çerçevesi singleton desenlerini kullanmak yaygın ve iyi anlaşılmıştır. Bunu yapmazsanız, her yerde kayıt cihazları oluşturup enjekte ediyorsunuz ve bunu istemiyorsunuz.

Yukarıdakilerden biri, birinin ' diyecekleri günlüğü nasıl test edebilirim? . Düşüncelerim, normal olarak günlükleri sınamadığım, günlük dosyalarını gerçekten okuyabildiğimi ve onları anlayabileceğimi iddia etmem. Günlük kaydını test ettiğimi gördüğümde, genellikle birinin bir sınıfın gerçekten bir şey yaptığını iddia etmesi ve bu geribildirimi almak için günlük mesajlarını kullanması gerektiğini iddia etmesi gerekir . Bu sınıfa bir dinleyici / gözlemci kaydetmeyi ve çağrılan sınavlarıma atıfta bulunmayı tercih ederim. Daha sonra olay günlüğünü o gözlemcinin içine koyabilirsiniz.

Ancak, önbelleklemenin tamamen farklı bir senaryo olduğunu düşünüyorum.


3
Şimdiye dek biraz FP ile uğraşırken, günlükleri, hata işlemesi vb. Gibi şeyleri çekirdek iş mantığına koymadan kullanım davalarınıza yerleştirmek için (belki monadik) fonksiyon bileşimini kullanmaya büyük ilgi göstermeye başladım. bkz. fsharpforfunandprofit.com/rop )
sara

5
Günlük tutma yaygın olmamalıdır . Eğer öyleyse, o zaman çok fazla giriş yapıyorsunuzdur ve gerçekten bu kayıtlara bakmanız gerektiğinde kendiniz için gürültü yaratıyorsunuzdur. Kaydedici bağımlılığını enjekte ederek, bir şeyi gerçekten kaydetmeniz gerekip gerekmediğini düşünmek zorunda kalırsınız.
RubberDuck

12
@RubberDuck - Alandan bir hata raporu aldığımda "günlüğe kaydetmenin yaygın olmaması gerektiğini" ve ne olduğunu bulmak zorunda olduğum tek hata ayıklama yeteneğinin, yaygın hale getirmek istemediğim o günlük dosyası olduğunu söyle. Alınan ders, kütük kaydı "yaygın", çok yaygın olmalı.
Dunk

15
@RubberDuck: Sunucu yazılımı ile hayatta kalmak için tek yol günlüğe kaydetmedir. Şu anda kendi dizüstü bilgisayarınızda 12 saat önce olan bir hatayı bulmanın tek yolu bu. Gürültü hakkında endişelenme. Günlüğünüzü sorgulayabilir kullanın; böylece günlük yönetim yazılımı (ideal ayrıca hata günlükleri size e-posta alarmları kurmak gerekir)
slebetman

6
Destek ekibimiz beni aradı ve "müşteri bazı sayfaları tıklattı ve bir hata oluştu" dedi. Onlara hatanın ne dediğini sordum, bilmiyorlar. Müşterinin özellikle ne tıklattığını soruyorum, bilmiyorlar. Tekrar üretebilecekler mi, yapamazlar diye soruyorum. Günlüğe kaydetme işleminin çoğunlukla birkaç kilit menteşe noktasında iyi konuşlandırılmış kayıt cihazlarıyla gerçekleştirilebileceğini kabul ediyorum, ancak buradaki küçük garip mesajlar da paha biçilmez. Kayıt korkusu düşük kaliteli yazılıma yol açar. Çok fazla veri ile bitiyorsanız, geri budamak. Erken optimize etmeyin.
Pace

12

2 sentim ...

Evet ve hayır.

Sen asla gerçekten evlat ilkelerini ihlal; ancak, ilkeleriniz daima daha yüksek bir amaca hizmet etmek için nüanslı olmalı ve benimsenmelidir. Bu nedenle, düzgün bir şekilde şartlandırılmış bir anlayışla, bazı bariz ihlaller "ruh" un veya "bir bütün olarak ilkeler bedeninin" gerçek ihlalleri olmayabilir .

Özellikle SOLID ilkeleri, çok fazla nüans gerektirmesine ek olarak, nihayetinde “çalışan, bakımı yapılabilir yazılım sağlama” hedefine tabidir. Bu nedenle, herhangi bir SOLID ilkesine bağlı kalmak, SOLID'in hedefleriyle çelişen, kendini yitiren ve kendisiyle çelişen bir durumdur. Ve burada, sık sık kozlar sürdürebilirlik sağladığını not ediyorum .

Yani, ne hakkında D de KATI ? Peki, yeniden kullanılabilir modülünüzü bağlamına göre oldukça agnostik hale getirerek, sürdürülebilirliğin arttırılmasına katkıda bulunur. Ve "yeniden kullanılabilir modülü" "başka bir bağlamda kullanmayı planladığınız bir kod koleksiyonu" olarak tanımlayabiliriz. Ve bu, tek bir fonksiyona, sınıflara, sınıf kümelerine ve programlara uygulanır.

Ve evet, değişen logger uygulamaları muhtemelen modülünüzü "başka bir bağlam" a yerleştirir.

Öyleyse iki büyük uyarımı önereyim :

Birincisi: “Yeniden kullanılabilir bir modül” oluşturan kod bloklarının etrafındaki çizgilerin çizilmesi profesyonel bir yargı meselesidir. Ve kararın mutlaka tecrübenle sınırlı.

Şu anda başka bir bağlamda bir modül kullanmayı düşünmüyorsanız , çaresizce ona bağlı kalmak büyük olasılıkla iyidir . Uyarıya ilişkin uyarı: Planlarınız büyük olasılıkla yanlıştır - ama bu da sorun değil. Modülden sonra ne kadar uzun süre modül yazarsanız, "bir gün tekrar ihtiyacım olacak" anlayışı ne kadar sezgisel ve doğru olacaktır. Ancak, muhtemelen hiç bir zaman geriye dönük olarak “Her şeyi mümkün olan en büyük ölçüde modüler hale getirdim ve ayrıştırdım, ancak fazlalık olmadan ” diyemeyeceksiniz .

Yargılamadaki hatalarından dolayı kendini suçlu hissediyorsan, itirafa git ve devam et ...

İkincisi: Ters çevirme kontrolü enjekte bağımlılıklarına eşit değildir .

Bu özellikle bağımlılıkları enjekte etmeye başladığınızda geçerlidir . Bağımlılık Enjeksiyonu, kapsamlı IoC stratejisi için yararlı bir taktiktir. Ancak, DI'nin diğer taktiklerden daha az etkili olduğunu savunuyorum - arayüzler ve adaptörler kullanmak gibi - modülün içeriğine tek maruz kalma noktaları.

Ve hadi buna bir saniye odaklanalım. Çünkü, bir reklam nauseam enjekte etmiş olsanız bile , arayüze karşı kod yazmanız gerekir . Parametreleri farklı sırada alan farklı bir satıcıdan yeni bir ürün kullanmaya başlayamazsınız . Bu yetenek, modül içinde, modül içinde var olan ve bağımlılığı yönetmek için tek bir alt modüle (Adaptör) sahip olan bir arayüze karşı kodlamadan gelir .Logger LoggerLogger

Bir Adaptöre karşı kodlama yapıyorsanız, Loggero Adaptöre enjekte edildiğinde veya Adaptör tarafından keşfedildiğinde, genel olarak genel bakım hedefine önemsizdir. Daha da önemlisi, modül düzeyinde bir Adaptöre sahipseniz, muhtemelen herhangi bir şeye enjekte etmek saçmadır. Modül için yazılmış .

tl; dr - Prensipleri neden kullandığınıza dikkat etmeden prensipler hakkında endişelenmeyi bırakın. Ve daha pratik olarak, sadece Adapterher modül için bir tane oluşturun. "Modül" sınırlarını nereye çizeceğinize karar verirken kararınızı kullanın. Her modülün içinden devam edin ve doğrudan Adapter. Ve tabii, enjekte gerçek logger içine Adapterancak - değil o gerekebilir her küçük şeyin içine.


4
Dostum ... Daha kısa bir cevap verirdim ama vaktim olmadı.
svidgen

2
Adaptör kullanmak için +1. Mümkün olan her yerde değiştirilebilmeleri için, üçüncü taraf bileşenlere olan bağımlılıkları izole etmeniz gerekir. Günlüğe kaydetme bunun için kolay bir hedeftir - birçok kayıt uygulaması mevcuttur ve çoğunlukla benzer API'lere sahiptir, bu nedenle basit bir adaptör uygulaması bunları kolayca değiştirmenize izin verebilir. Ve günlük sağlayıcınızı asla değiştiremeyeceğinizi söyleyenlere: Bunu yapmak zorunda kaldım ve gerçek bir acıya neden oldu çünkü adaptör kullanmıyordum.
Jules

“Özellikle SOLID ilkeleri, çok fazla nüans gerektirmesine ek olarak, nihayetinde“ çalışan, bakımı yapılabilir yazılım sağlama ”hedefine tabidir.” "- Bu gördüğüm en iyi ifadelerden biri. Hafif bir OKB kodlayıcısı olarak idealizm ve üretkenlikle mücadeledeki payımı paylaştım.
DVK

Ne zaman eski bir cevaba bir +1 veya yorum görsem, cevabımı tekrar okudum ve yine çok dağınık ve net olmayan bir yazar olduğumu keşfediyorum. Yine de @DVK.
svidgen

Adaptörler can koruyuculardır, çok pahalı değildirler ve özellikle SOLID uygulamak istediğinizde hayatınızı çok daha kolay hale getirir. Test onlarla bir esinti.
Alan

8

Günlüğe kaydetmenin her zaman bir singleton olarak uygulanması gerektiği düşüncesi, çok sık söylenen yalanlardan biridir.

Modern işletim sistemleri hakkında olduğu sürece , çıktının doğasına bağlı olarak birden fazla yere giriş yapmak isteyebileceğiniz kabul edilmiştir .

Sistem tasarımcıları, geçmiş çözümlerin etkinliğini, körlerini yenilere eklemeden önce sürekli sorgulamalıdır. Eğer böyle bir özen göstermiyorlarsa, o zaman işlerini yapmıyorlar.


2
Öyleyse önerdiğiniz çözüm nedir? Yazdığınız her sınıfa bir ILogger mı enjekte ediyor? Bir Dekoratör deseni kullanmaya ne dersiniz?
Robert Harvey,

4
Şimdi sorumu cevaplamıyorsun değil mi? Kalıpları sadece örnek olarak söyledim ... Aklında daha iyi bir şey varsa, bunların olması gerekmez.
Robert Harvey,

8
Somut teklifler açısından bu cevabı gerçekten anlamıyorum
Brian Agnew

3
@RobbieDee - Yani, Günlüğe kaydetmenin en karmaşık ve elverişsiz şekilde, birden fazla yere giriş yapmak isteyebileceğimiz "şanssız" yöntemiyle uygulanması gerektiğini söylüyorsunuz. Böyle bir değişiklik meydana gelse bile, bu Logger örneğine bu işlevselliği eklemenin, Logger istediğinizi seçip seçmeme konusunda karar verdiğinizde, sınıflar ve ara yüzleri değiştirmek arasında bu Logger'ı geçirme çabalarından daha fazla işe yarayacağını düşünüyor musunuz? bu çoklu yer kayıtlarının asla gerçekleşmeyeceği düzinelerce proje?
Dunk

2
Re: "çıktının yapısına bağlı olarak birden fazla yere giriş yapmak isteyebilirsiniz": Tabii, ancak birden fazla ayrı günlük bağımlılığı enjekte etmeye çalışmak yerine, bunu günlükleme çerçevesindeki en iyi şekilde ele almanın yolu . (Yaygın günlük çerçeveler zaten bu destekler.)
ruakh

4

Gerçekten giriş yapmak özel bir durumdur.

@Telastyn yazıyor:

Günlük kitaplığınızı, hedefinizi veya filtreleme ya da biçimlendirme veya ...

Günlük kitaplığınızı değiştirmeniz gerekebileceğini düşünüyorsanız, bir cephe kullanmanız gerekir; yani eğer Java dünyasındaysanız SLF4J.

Gerisi, iyi bir günlük kütüphanesi günlüğün nereye gittiğini, hangi olayların filtrelendiğini, log olay konfigürasyon dosyaları ve (gerekirse) özel eklenti sınıfları kullanılarak log olaylarının nasıl biçimlendirileceğini değiştirmeye özen gösterir. Bir dizi kullanıma hazır alternatif var.

Kısacası, bunlar kayıt için ... çözülmüş problemlerdir ... ve dolayısıyla bunları çözmek için Bağımlılık Enjeksiyonunu kullanmaya gerek yoktur.

DI'nin yararlı olabileceği tek durum (standart kayıt yaklaşımlarına göre), uygulamanızın kayıt işlemlerini ünite testine tabi tutmak isteyebilirsiniz. Ancak, ben şüpheli çoğu geliştirici bu günlüğü bir sınıflar işlevsellik parçası olduğundan ve bu bir şey değildir söyleyebilirim ihtiyaçlarını test edilecek.

@Telastyn yazıyor:

Ve sonra, kaydedicinin kendisinin değişikliği ele alacağı argümanını elde edersiniz. "Ah, hedef / filtreleme / biçimlendirme / strateji değişirse, o zaman sadece config'u değiştiririz!" Bu çöp. Artık sadece bunların hepsini işleyen bir Tanrı Nesnesine sahip değilsiniz, kodunuzu XML (veya benzer) bir şekilde yazıyorsunuz, statik analiz yapmıyorsunuz, derleme zamanı hataları almıyorsunuz ve Gerçekten etkili birim testleri almazsınız.

Korkarım bu çok teorik bir sonuçtur. Uygulamada, çoğu geliştirici ve sistem entegratörü LIKE'ı, günlüğü bir config dosyası aracılığıyla yapılandırabileceğiniz gerçeğidir. Ve onlar bir modülün kayıt işleminde ünite testi yapmasının beklenmemesi gerçeğini severler.

Tabii, eğer günlük yapılandırmalarını doldurursanız sorun yaşayabilirsiniz, ancak bunlar uygulama sırasında başarısız olan veya çok / çok küçük günlük kaydı olarak ortaya çıkacaktır. 1) Bu dosyalar config dosyasındaki hatayı düzelterek kolayca çözülebilir. 2) Alternatif, kayıt seviyelerinde her değişiklik yaptığınızda tam bir derleme / analiz / test / dağıtım döngüsüdür. Bu kabul edilebilir değil.


3

Evet ve hayır !

Evet: Farklı alt sistemlerin (veya semantik katmanlar veya kütüphaneler veya diğer modüler donatılma kavramlarının) her birinin aynı ortak paylaşılan singleton'a dayanan tüm alt sistemlerden ziyade , başlatma sırasında potansiyel olarak farklı kayıt cihazlarını kabul etmesinin makul olduğunu düşünüyorum .

Ancak,

Hayır: aynı zamanda her küçük nesnede (yapıcı ya da örnek yöntemiyle) günlüğe kaydetmeyi parametrelendirmek mantıksızdır. Gereksiz ve anlamsız şişkinlikten kaçınmak için, küçük işletmeler, kendi içindekiler bağlamındaki tekil kayıt cihazını kullanmalıdır.


Bu, diğerlerinin arasında seviyelerde modülerliği düşünmenin bir nedenidir: yöntemler sınıflara, sınıflar alt sistemler ve / veya anlamsal katmanlara paketlenir. Bu daha büyük demetler değerli soyutlama araçlarıdır; modüler sınırlar içinde, onları geçtikten daha farklı düşünceler vermeliyiz.


3

İlk önce güçlü tekil önbellekle başlar, bir sonraki göreceğiniz şey, genel durum, açıklayıcı olmayan classes'ler ve test edilemeyen kod içeren veritabanı katmanı için güçlü tekillerdir.

Bir veritabanı için bir singleton'a sahip olmamaya karar verirseniz, muhtemelen bir önbellek için singleton'a sahip olmak iyi bir fikir değildir, sonuçta, sadece farklı mekanizmalar kullanarak çok benzer bir kavramı, veri depolamayı temsil eder.

Bir sınıfta bir singleton kullanmak, teorik olarak sınırsız sayıda sınıfa sahip olan bir sınıfa belirli miktarda bağımlılığı olan bir sınıfı döndürür , çünkü statik yöntemin gerçekte ne gizli olduğunu asla bilemezsiniz.

Geçtiğimiz on yıl boyunca programlamayı harcadım, kayıt mantığını değiştirme çabasına tanık olduğum tek bir vaka vardı (bu daha sonra singleton olarak yazılmıştı). Bu yüzden bağımlılık enjeksiyonlarını sevmeme rağmen, kayıt olmak gerçekten çok büyük bir endişe değil. Önbellek, diğer taraftan, kesinlikle her zaman bir bağımlılık yapardım.


Evet, günlük kaydı nadiren değişir ve genellikle değiştirilebilen bir modül olmak zorunda değildir. Ancak, bir keresinde kayıt sistemine statik bir bağımlılığı olan bir kayıt yardımcı sınıfını test etmeye çalıştım. Test edilebilirliği test etmenin en kolay mekanizmasının, sınıfı ayrı bir işlemde test altında çalıştırmak, kaydedicisini STDOUT'a yazacak şekilde yapılandırmak ve benim test örneğindeki bu çıktıyı ayrıştırmak olduğuna karar verdim. d açıkçası gerçek zamandan başka hiçbir şey istemiyor, değil mi? Elbette, zaman dilimini / DST sınır durumları test ederken ... hariç
amon

@ amon: Saatler, DI ile aynı amaca hizmet eden, yani Joda-Time ve birçok bağlantı noktası olan başka bir mekanizma olduğu için oturum açmak gibidir. (Bunun yerine DI'yi kullanmakta yanlış olan bir şey yoktur; ancak Joda-Time'ı doğrudan özel bir enjekte edilebilir adaptör yazmayı denemekten daha kolaydır ve bunu yaparken pişman olan birini görmedim.)
ruakh

@ amon "Açıkça gerçek zamandan başka hiçbir şey istemeyeceğiniz saatlerle benzer bir deneyimim oldu, doğru mu? Tabi ki saat dilimi / DST edge vakalarını test ederken, elbette…" - veya bir hatanın olduğunu fark ettiğinizde veritabanınızı bozdu ve geri almanın tek umudu, olay günlüğünüzü ayrıştırmak ve son yedeklemeden başlayarak tekrar oynatmaktır ... ancak aniden, geçerli günlük yerine geçerli günlük girişinin zaman damgasına dayanarak çalışmak için tüm kodunuza ihtiyacınız olur. saati.
Jules

3

Evet ve Hayır, ama çoğunlukla Hayır

Konuşmanın çoğunun statik vs enjekte edilen örneğe dayandığını varsayıyorum. Kimse günlüğe kaydetmenin varsaydığım SRP'yi kırmasını önermiyor mu? Biz esas olarak “Bağımlılık inversiyon ilkesi” hakkında konuşuyoruz. Tbh Ben çoğunlukla Telastyn’in cevabı olmadığını kabul ediyorum.

Statiği kullanmak ne zaman uygundur? Çünkü açıkça, bazen sorun değil. Evet cevapları, soyutlamanın yararları ve “hayır” cevapları, ödediğiniz bir şey olduğuna işaret eder. İşinizin zor olmasının sebeplerinden biri, yazabileceğiniz ve tüm durumlara uygulayabileceğiniz bir cevap olmaması.

atın: Convert.ToInt32("1")

Bunu tercih ederim:

private readonly IConverter _converter;

public MyClass(IConverter converter)
{
   Guard.NotNull(converter)
   _converter = conveter
}

.... 
var foo = _converter.ToInt32("1");

Neden? Dönüşüm kodunu değiştirmek için esnekliğe ihtiyacım olursa kodu yeniden düzenlemem gerekeceğini kabul ediyorum. Bunu alamayacağımı kabul ediyorum. Sadelik ve açıklığın bu ticarete değer olduğuna inanıyorum.

Eğer yelpazenin diğer ucunda baktığımızda, IConverterbir oldu SqlConnection, ben oldukça statik bir çağrı olarak görmek dehşete düşecek. Neden açıkça bariz olduğu açık. SQLConnectionBir uygulamada bir "oldukça kesik" olabileceğine işaret ederdim , bu yüzden bu kelimeleri kullanmazdım.

Günlüğe kaydetme daha çok mu SQLConnectionyoksa Convert.ToInt32? 'SQLConnection' gibi daha fazla söyleyebilirim.

Günlük ile alay ediyor olmalısın . Dış dünyayla konuşuyor. Kullanarak bir yöntem yazarken Convert.ToIn32, sınıfın diğer ayrı test edilebilir çıktılarını hesaplamak için bir araç olarak kullanıyorum. ConvertBu "1" + "2" == "3" işaretini kontrol ederken doğru olarak kontrol edilmesine gerek yoktu. Günlük kaydı farklıdır, bu sınıfın tamamen bağımsız bir çıktısıdır. Bunun sizin, destek ekibinin ve işin değeri olan bir çıktı olduğunu farz ediyorum. Günlük kaydı doğru değilse sınıfınız çalışmaz, bu nedenle ünite testleri geçmemelidir. Sınıfınızın neler kaydettiğini test ediyor olmalısınız. Bunun katil argüman olduğunu düşünüyorum, burada gerçekten durabilirim.

Ayrıca değişmesi oldukça muhtemel bir şey olduğunu düşünüyorum. İyi günlüğe kaydetme yalnızca dizeleri yazdırmakla kalmaz, uygulamanızın ne yaptığını da gösterir (Ben olay temelli günlüğe kaydetmenin büyük bir hayranıyım). Temel kayıtların oldukça ayrıntılı raporlama kullanıcı arayüzlerine dönüştüğünü gördüm. Günlük kaydınız _logger.Log(new ApplicationStartingEvent())daha az benziyorsa, bu yöne doğru gitmeniz çok daha kolay Logger.Log("Application has started"). Birisi bunun asla gerçekleşmeyecek bir gelecek için envanter oluşturduğunu iddia edebilir, bu bir yargılama çağrısı ve buna değer olduğunu düşünüyorum.

Aslında benim kişisel bir projemde _logger, uygulamanın ne yaptığını anlamak için tamamen kullanan bir kullanıcı arayüzü oluşturdum . Bu, uygulamanın ne yaptığını anlamak için kod yazmak zorunda olmadığım anlamına geliyordu ve çok sağlam bir kayıt tuttum. Günlük tutmaya olan tutumum basit ve değişmez ise, bu fikir benim başıma gelmezmiş gibi hissediyorum.

Bu yüzden günlüğe kaydetme davası için Telastyn ile hemfikirdim.


Bu şekilde tesadüfen giriş yapıyorum . Bir makaleye ya da bir şeye bağlanmak istiyorum, ancak bir tane bulamıyorum. .NET dünyasındaysanız ve olay günlüğüne bakın, bulacaksınız Semantic Logging Application Block. Kullanmayın, MS "kalıpları ve pratik" ekibi tarafından oluşturulan kodun çoğu gibi, ironik olarak, bu bir antipattern.
Nathan Cooper

3

İlk Kesişme endişeleri ana yapı taşları değildir ve bir sistemdeki bağımlılıklar olarak değerlendirilmemelidir. Logger başlatılmadıysa veya önbellek çalışmıyorsa, bir sistem çalışmalıdır. Sistemi nasıl daha az bağlı ve tutarlı hale getireceksiniz? SOLID, OO sistem tasarımında resme girdiği yer.

Nesneyi tekil olarak tutmak, SOLID ile ilgisi yoktur. Nesnenin ömründe, nesnenin hafızada ne kadar süre yaşamasını istediğin bu.

Başlatmak için bağımlılık gerektiren bir sınıf, verilen sınıf örneğinin tekil mi yoksa geçici mi olduğunu bilmemelidir. Ancak tldr; Her yöntem veya sınıfta Logger.Instance.Log () yazıyorsanız, o zaman sorunlu bir kod (kod kokusu / sabit bağlantı) gerçekten dağınık olanıdır. Bu, insanların SOLID'i kötüye kullanmaya başladığı andır. OP gibi diğer geliştiriciler de bunun gibi gerçek bir soru sormaya başlar.


2

Bu sorunu miras ve özelliklerin bir kombinasyonunu kullanarak çözdüm (bazı dillerde mixins olarak da bilinir). Bu tür bir çapraz kesim sorununu çözmek için özellikler çok kullanışlı. Bu genellikle bir dil özelliği olsa da, asıl cevabın dil özelliklerine bağlı olduğunu düşünüyorum.


İlginç. Nitelikleri destekleyen bir dil kullanarak hiç önemli bir iş yapmadım, ancak gelecekteki bazı projeler için bu dilleri kullanmayı düşündüm, bu yüzden bunu genişletebilirseniz ve özelliklerin sorunu nasıl çözeceğini göstermem bana yardımcı olacaktır.
Jules
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.