Günlük kodunu tamamen iş mantığının dışında tutmak mümkün müdür?


12

AOP yardımı ile günlük kodunu iş mantığımdan kaldırabilirim. Ama sadece basit şeyler (yani günlükleme yöntemi giriş / çıkış ve parametre değerleri) günlüğe kaydetmek için kullanılabilir düşünüyorum.

Ancak, iş mantığımda bir şey kaydetmem gerekirse ne olur? Örneğin

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      Log.Warn("user is not existed");        //<----------------- Log A
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   Log.Info("Step 1 is completed");            //<----------------- Log B

   //Step 2
   while(true)
   {
       //do something
   }
   Log.Info("Step 2 is completed");            //<----------------- Log C

}

Yukarıdaki örnek yöntem yeterince açık olmayabilir, burada göstermek istediğim, yöntemin etki alanı açısından en küçük birim olarak ele alınması gerektiğidir. Daha küçük parçalara bölünmemelidir.

3 günlük kodunun üstünde yöntemin dışına çıkmak mümkün mü? Böyle bir durum için en iyi uygulama nedir?


Örneğinizin "Adım1" ve "Adım2" günlüklerinin bir iş mantığı denetim yolunun ve ilkinin teknik bir günlük kaydının parçası olması gerektiğinden eminim. Ben ilk önce bu tür ...
tofro

Yanıtlar:


1

Elbette!

Ancak tecrübelerime göre, iki genel yararlı günlük kaydı türü vardır :

Her şey günlüğe kaydediliyor: Profil oluşturma API'leri aracılığıyla oluşturulan günlükler . Performans sorunlarını tanımlamak ve istisnaları bildirmek için iyidir. Çok gürültülü.

İş olay günlükleri: İş mantığında çağrılan günlükler . İşletmenin ilgilenebileceği her şey. Minimum gürültü. Sadece dikkate değer, mantıklı, "iş" etkinlikleri. Denetim ve KPI'lar için iyi ...

Bu yüzden iki şey öneriyorum. İlk olarak, New Relic gibi diğer izleme araçlarının yaptıklarını yapın ve .NET profili API 1'i kullanın . İkinci olarak, iş mantığınızdaki mantıksal iş olaylarını günlüğe kaydedin . Belli etkinliklerin kaydını tutmak olduğunu iş mantığı.

Ve normalde giriş birini tür için AOP'yi önermek olmaz 2 . Deneyimlerime göre, ya her şeyi istersiniz , yani bir profil oluşturucu kullanırsınız ya da mantıksal / ticari etkinlikler istersiniz. İkinci durumda, logger'ı iş mantığında çağırmanın daha basit olduğunu düşünüyorum .


1. Ama cidden, kendinize binlerce saat çaba sarf edin ve sadece mevcut bir profil oluşturma aracını kullanın ...

2. Elbette, bu, bir yönün iş kurallarını gizlemek için harika bir yer olmadığı fikrimi paylaştığınızı varsayar !


"İş etkinliği günlükleri" konusunda oldukça katılıyorum ve diğerlerinin yanıtları gibi, günlük kodunu iş mantığında tutacağım. "Her şey günlüğe kaydeder" bölümü için, SRP'yi izleyeceği ve iş mantığımı kirletmeyeceği için AOP çözümünü kullanmayı tercih ederim. Her neyse, öncelikle profilleme API'sine bir göz atacağım.
Charlie

10

Elbette, bunun için AOP'yi kolayca kullanabilirsiniz. Sadece parçaları yeniden düzenleyin

  • Kullanıcıyı kimliğe göre al
  • Aşama 1
  • Adım 2

içine ayrı yöntemlerle (eğer kod temiz hale getirme ya yapmalıydım gibi). Artık, seçtiğiniz yöntem çağrılarını ( burada gösterildiği gibi ) kaydetmek için AOP çerçevenizi kolayca yapılandırabilirsiniz . İstisna doğrudan arayan tarafından kaydedilebilir, bunu iş mantığından çıkarmak için AOP kullanmaya gerek yoktur.

Düzenlemeniz için:

Burada, yöntemin etki alanı açısından en küçük birim olarak ele alınması gerektiğini göstermek istiyorum. Daha küçük parçalara bölünmemelidir

Neden olmasın? Bir "iş mantığı bağlamında", günlüğe kaydetmeye değer "bir şey" kaydetmek istiyorsanız ve bu "bir şey" mantıklı bir ad verilebiliyorsa, çoğu durumda kodu bir yönteme dönüştürmek mantıklı olacaktır Kendi. AOP'yi kullanmak istiyorsanız, kodunuzu, günlük kaydı gereksinimine bakılmaksızın büyük olasılıkla yapılandırmanız gereken bir şekilde yapılandırmanızı gerektirir. Bunu AOP'nin bir dezavantajı olarak yorumlayabilir veya bir fayda olarak yorumlayabilirsiniz, çünkü size kod yapınızın iyileştirilebileceği bir geri bildirim sağlar.


Benim örneğim yeterince açık değil. Aslında örnekte göstermek istediğim, yöntemin etki alanı açısından daha küçük parçalara bölünmemesi gereken en küçük birim olmasıdır.
Charlie

@Charlie: örnek çok açık. Buradaki yanlış kanı muhtemelen adımlardan daha büyük yöntemlere sahip olmanın iyi bir fikir olabileceğini düşünüyor. Ve bu IMHO yanlış, iyi bir fikir değil. Günlüğe kaydetmeye değer farklı adımlara sahip olmak, bu adımların bir soyutlamaya, kendi başına bir isme, dolayısıyla kendi başına bir yönteme sahip olması gerektiğinin açık bir işaretidir.
Doc Brown

@Charlie hiçbir şey birim veya iş tarafından çağrılan 3 özel yöntem yapmanıza engel değildir. Bu şekilde dışarıdan aynı kaldı ama şimdi günlük kaydı için gerekli soyutlama var.
Rémi

Endişeleri günlüğe kaydederek kod yapınızı yönlendirmek istiyorsanız bu yaklaşım uygundur. Bazen başka bir şey tarafından sürmek istersiniz.
John Wu

@JohnWu: Kod yapısı, günlük kaydı gereksiniminden bağımsız olarak farklı endişeleri / adımları yansıtmalıdır. Yani burada kod yapısını teşvik olmaktadır. Bu sorun çözüldükten sonra, günlük kaydı AOP tarafından yapılabilir, bu da koda daha iyi bir yapı kazandırmanın bir "yan etkisi" dir. Bu yüzden kod yapısını yönlendiren günlüğe kaydetme kaygısı olmadığını düşünüyorum, bu daha çok günlüğe kaydetme için AOP kullanma gereksinimi kodun olması gereken bazı yapı özlüyor daha şeffaf hale getirir.
Doc Brown

3

Günlüğe kaydetme, iş gereksinimlerinin bir parçası olmadığı sürece, söylediğiniz gibi, kodunuzdan tamamen uzak tutmak için en iyisidir.

Bu, "1. adım tamamlandı" gibi şeyleri gerçekten kaydetmek istemediğiniz anlamına gelir. Başlangıçta hata ayıklama için yararlı olsa da, üretimde sadece bakmayacağınız gigabayt çöp üretecektir.

Step1Complete, daha fazla işlem gerektiren bir tür iş etkinliğiyse, sınıfınıza bir ILogger veya benzeri enjekte etmeye zorlamadan eski moda bir etkinlikle ortaya çıkabilir.


Düşündüğüm şey buydu. Bir etki alanı / iş modeli POCO'sunda oturum açmak için makul bir durum bulamıyorum. Günlüğe kaydetme, temel iş modellerinin (IMO) dışına doğal olarak uyma eğiliminde olan bir şeydir.
jleach

2

Bazı yaygın kalıpların yardımıyla günlük kodunu iş mantığınızdan çıkarabilirsiniz. Ancak buna değer bulmayabilirsiniz

Örneğin, dinleyici kullanarak (bir tane el sanatları veya olay veri yolu vb. Kullanarak), kodunuz

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      listener.OnUserNotFound(userId);
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   listener.OnStep1Finished(......);

   ...

}

Günlüğe kaydetmeyi dinleyiciye uygulayarak, günlüğe kaydetme mantığı artık iş mantığınızda yer almaz.

Bununla birlikte, mantığınızın anlamlı olayını her zaman tanımlayamayabileceğinizden, bunun her zaman gerçekçi olmadığını görebilirsiniz.

Başka bir yaklaşım, çalışan süreçlere enjekte etmenizi sağlayan Dtrace in Solaris gibi bir mekanizmadır (C #? Da benzer bir şey yapmanın bir yolu olduğuna inanıyorum), böylece kayıt ve istatistik toplantıları çalışma zamanında tanımlanabilir. Yine de başka dezavantajlar var.


AOP'nin çözmeye çalıştığı sorunlardan biri, kodun "iş kodu" ile iç içe geçmiş iş dışı kodun (günlük kaydı gibi) okunamayan sorunudur. Bir "kaydediciyi" bir "dinleyici" ile değiştirmek bunu çözmez, kodun okunabilirliği değişmez,
Doc Brown

2

Başka bir yaklaşım, iş günlüğü ve teknik günlüğü ayırmaktır. Daha sonra, iş günlüğü "Denetim" olarak adlandırılabilir ve depolama süresi ve İş Etkinliği İzleme gibi işleme kuralları gibi belirli bir iş kuralları kümesi uygulayabiliriz.

Öte yandan, teknik kayıt veya basitçe "Kayıt", teknik sorunun izini bırakmanın son yoludur. Günlük iletisinin devam edememesine zaman uyumsuz, hızlı, toleranslı olmalıdır. Ayrıca, günlük iletileri, sorunun kaynağına yakın olabilmesi için mümkün olan en az sayıda proxy'den geçmelidir.

The Logging of The Logging oldukça değişkendir ve uygulama ile sıkı sıkıya bağlıdır, bu yüzden gerçekten koddan ayırmanız gerekir mi?

Denetim Mantığı bir etki alanı mantığı olarak değerlendirilmeli ve buna göre ele alınmalıdır.

Örneğin, Altıgen Mimari'de İstemciler, Depolama ve MQ (ve muhtemelen Metrikler ve Kontrol) bağlantı noktaları ile birlikte Denetim bağlantı noktası olabilir. İkincil bağlantı noktası olacaktır, yani bu bağlantı noktasındaki etkinlik, dış sistemler yerine iş merkezi tarafından tetiklenir.


İki çeşit günlük kaydı olduğuna çok katıldım. Ama Logging of The Logging'in oldukça değişken olduğunu ve uygulamaya sıkı sıkıya bağlı olduğunu anlamıyorum, burada teknik kayıt mı demek istiyorsun? Teknik günlüğe kaydetme için, yöntemin dışında oturmak daha iyi olan yöntem giriş / çıkış ve parametre değerlerini günlüğe kaydetmek için kullanıldığını düşünüyorum.
Charlie

@Charlie Evet, "The Logging" ile teknik kayıt demek istiyorum. Saf fonksiyonlarda giriş / çıkış / parametre değerlerinin kaydedilmesi yeterlidir. Daha sonra, ya da rotada, bir yönü ya da Logger monadını kullanabilirsiniz. Ancak saf fonksiyonlar test edilebilir olmaları açısından harikadır. Yani, günlükçünün izlemesi gereken sorunlar, dev / debug sırasında çözülmesi muhtemeldir. Teknoloji günlüğünün en çok kullanıldığı saf olmayan işlevlerle, her yan etkili çağrı parametresini / sonucunu, her istisnayı günlüğe kaydetmek istersiniz.
iTollu

1

Doğrudan bir sınıfta veya yöntemde günlüğe kaydetmeyi önlemenin yolları:

  1. Bir istisna atın ve çağrı ağacınızı daha yukarıdaki bir catch bloğuna giriş yapın. Bir günlük düzeyi yakalamanız gerekiyorsa, özel bir istisna atayabilirsiniz.

  2. Günlüğe kaydetme için zaten kullanılan yöntemlere çağrı yapın.


1
Günlüğe kaydetme, sorun olduğu ve hatta "düzeltmeye" değer olduğu gösterildi mi?
whatsisname

1

Günlük kaydını iş mantığınızdan ayırmak gerçekten gerekli mi? Günlük kaydı, yazılan iş mantığına uygundur ve bu nedenle aynı sınıfta / işlevde olmak mantıklıdır. Daha da önemlisi, kodun daha kolay okunmasına yardımcı olur.

Ancak, günlük kaydını gerçekten iş mantığınızdan ayırmak istiyorsanız, özel istisnalar atmayı ve bu istisnaları günlük kaydı için teslim etmeyi düşünmelisiniz.


0

Hayır, c # 'da değil

OP, özel sorunuzun cevabı hayır, c # değil. Orada başka, daha doğal AOP dilleri olabilir, ancak gördüğüm c # 'daki tüm AOP yaklaşımları yalnızca bir birleşim noktası bağlamında, etkilenen davranışları uygulayabilir , yani bir kod bloğu ve bir diğeri. Görünen davranışlar, elbette başka bir yöntemi çağırmak dışında bir yöntemin ortasında yürütülmez.

Günlüğe kaydetmenin belirli parçalarını "apsect-ize" edebilirsiniz

Bununla birlikte, günlük yazmayla değil, günlükle ilgili bazı endişeleri çıkarabilirsiniz. Örneğin, bir yönteme girişte yürütülen bir kesme noktası, bir günlük kaydı bağlamı ayarlayabilir ve tüm giriş parametrelerini çıkarabilir ve çıkışta, istisnalar yakalanabilir veya kalıcı depolamada, bu tür bir şey kaydedilebilir.

Günlük yazma zaten bir boyut değil

Günlük yazma işleminin gerçekten de kesişen bir konu olmadığını da ekleyeceğim. En azından günlük kaydı hata ayıklama değil. Bunun kanıtı, bu yönün ne yapacağını tam olarak açıklayan kesişen bir gereklilik yazamamanızdır - her durum için spesifiktir, çünkü günlüğü yazmanın amacı, neler olduğunu yansıtmaktır. mantık ve her yöntemdeki mantık oldukça benzersiz olmalıdır (bakınız KURU ).

Başka bir deyişle, günlük yazma ile yazılmakta olan şeyler arasında ayrılmaz bir mantıksal bağımlılık vardır. Genelleştiremezsiniz.

Ancak denetim

Bir tür işlevsel günlük kaydı gereksiniminiz varsa (örneğin, reddedilmeme gereksinimini destekleyen denetim günlüğü ), o zaman bazıları, bu günlük yazma işlemlerini bir yöntemin ortasında yürütmeniz gerektiğinde bulursanız, kodunuzu en boy yönelimli düşünme ile tutarlı bir şekilde yapılandırmadınız. Bu durumda, ihtiyacınız olan ayrıntı düzeyini elde edene kadar kodu ayrı yöntemlere çıkarmalısınız.

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.