Dengan bantuan AOP, saya dapat menghapus kode logging dari logika bisnis saya. Tapi saya pikir itu hanya dapat digunakan untuk mencatat hal-hal sederhana (mis. Metode masuk / keluar dan nilai parameter).
Namun, bagaimana jika saya perlu mencatat sesuatu dalam logika bisnis saya? misalnya
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
}
Metode sampel di atas mungkin tidak cukup jelas, yang ingin saya tunjukkan di sini adalah bahwa metode tersebut harus diperlakukan sebagai unit terkecil dari sudut pandang domain. Seharusnya tidak dibagi menjadi potongan-potongan kecil.
Apakah mungkin memindahkan 3 kode log di atas dari metode ini? Apa praktik terbaik untuk situasi seperti itu?
c#
logging
separation-of-concerns
Charlie
sumber
sumber
Jawaban:
Tentu!
Namun dalam pengalaman saya, ada dua tipe umum logging yang bermanfaat :
Semua log: Log dibuat melalui profil API. Baik untuk mengidentifikasi masalah kinerja dan pengecualian pelaporan. Sangat berisik.
Log peristiwa bisnis : Log dipanggil dalam logika bisnis. Apa pun yang mungkin diperhatikan bisnis. Kebisingan minimal. Peristiwa penting, logis, "bisnis". Baik untuk audit dan KPI ...
Jadi, saya akan sangat menyarankan dua hal. Pertama, lakukan apa yang dilakukan oleh alat pemantauan lain, seperti New Relic, dan gunakan .NET profiling API 1 . Kedua, catat kejadian bisnis logis dalam logika bisnis Anda . Menyimpan catatan peristiwa tertentu adalah logika bisnis.
Dan, saya biasanya tidak menyarankan AOP untuk kedua jenis logging 2 . Dalam pengalaman saya, Anda menginginkan semuanya , yang berarti Anda menggunakan profiler, atau Anda menginginkan acara logis / bisnis. Dan dalam kasus terakhir, saya pikir lebih mudah untuk hanya memanggil logger dalam logika bisnis.
1. Tetapi serius, hemat diri Anda ribuan jam dalam upaya dan hanya menggunakan alat profiler yang ada ...
2. Tentu saja, ini mengasumsikan bahwa Anda berbagi pendapat saya bahwa suatu aspek bukanlah tempat yang bagus untuk menyembunyikan aturan bisnis!
sumber
Tentu, Anda dapat dengan mudah menggunakan AOP untuk ini. Cukup refactor bagian-bagiannya
menjadi metode terpisah (seperti yang seharusnya Anda lakukan untuk membuat kode Anda lebih bersih). Sekarang Anda dapat dengan mudah mengkonfigurasi kerangka kerja AOP Anda untuk mencatat panggilan metode pilihan Anda ( seperti yang ditunjukkan di sini ). Pengecualian dapat dicatat secara langsung oleh penelepon, tidak perlu menggunakan AOP untuk mengeluarkan ini dari logika bisnis.
Untuk hasil edit Anda:
Kenapa tidak? Jika, dalam "konteks logika bisnis", Anda ingin mencatat "sesuatu" yang layak dicatat, dan jika "sesuatu" ini dapat diberi nama yang masuk akal, dalam kebanyakan kasus akan masuk akal untuk merefleksikan kode menjadi metode itu sendiri. Jika Anda ingin menggunakan AOP, Anda harus menyusun kode dengan cara yang mungkin harus Anda susun terlepas dari persyaratan logging. Anda dapat menafsirkan ini sebagai kelemahan AOP, atau Anda dapat menafsirkan ini sebagai manfaat, karena memberi Anda umpan balik di mana struktur kode Anda dapat ditingkatkan.
sumber
Kecuali hal-hal Logging adalah bagian dari persyaratan bisnis maka yang terbaik, seperti yang Anda katakan, untuk sepenuhnya keluar dari kode Anda.
Itu berarti Anda benar-benar tidak ingin mencatat hal-hal seperti "langkah 1 selesai". Meskipun awalnya mungkin berguna untuk debugging, dalam produksi itu hanya akan menghasilkan gigabytes sampah yang Anda tidak akan pernah melihatnya.
Jika Step1Complete adalah semacam acara bisnis yang membutuhkan tindakan lebih lanjut maka itu dapat diekspos melalui acara kuno yang bagus tanpa memaksa Anda untuk menyuntikkan ILogger atau yang serupa ke dalam kelas Anda
sumber
Dengan bantuan beberapa pola umum Anda dapat menarik kode logging dari logika bisnis Anda. Namun Anda mungkin merasa tidak layak melakukannya
Misalnya, dengan menggunakan pendengar (kerajinan tangan atau menggunakan bus acara dll), kode Anda akan terlihat seperti
Dengan menerapkan pendataan di pendengar, logika pendataan tidak lagi ada dalam logika bisnis Anda.
Namun Anda mungkin menemukan ini tidak selalu realistis karena Anda mungkin tidak selalu dapat mendefinisikan peristiwa bermakna dari logika Anda.
Pendekatan lain adalah melalui mekanisme seperti Dtrace di Solaris yang memungkinkan Anda untuk menyuntikkan ke proses yang sedang berjalan (saya percaya ada cara untuk melakukan hal serupa di C #?) Sehingga logging dan pengumpulan statistik dapat didefinisikan pada saat runtime. Masih ada kekurangan lainnya.
sumber
Pendekatan lain adalah memisahkan pembalakan bisnis dan pembalakan teknis. Kemudian kita dapat menyebut pencatatan bisnis "Audit" dan menerapkan seperangkat aturan bisnis tertentu seperti istilah penyimpanan dan aturan pemrosesan seperti Pemantauan Aktivitas Bisnis.
Di sisi lain, penebangan teknis, atau hanya "Logging", adalah cara terakhir untuk meninggalkan jejak masalah teknis. Itu harus async, cepat, toleran terhadap kegagalan untuk mempertahankan pesan log. Juga, pesan log harus melewati paling sedikit jumlah proxy yang mungkin dekat dengan sumber masalah.
Logika Logging cukup variabel dan sangat erat dengan implementasinya, jadi apakah Anda benar-benar perlu memisahkannya dari kode?
Logika Audit harus dianggap sebagai logika domain dan ditangani sesuai itu.
Misalnya, dalam Arsitektur Heksagonal, mungkin ada port Audit bersama dengan port Klien, Storage dan MQ (dan, mungkin, Metrik dan Kontrol). Ini akan menjadi port sekunder, yaitu aktivitas pada port ini dipicu oleh inti bisnis, bukan oleh sistem eksternal.
sumber
Cara untuk menghindari masuk langsung ke kelas atau metode:
Lempar pengecualian, dan lakukan logging di blok tangkapan lebih jauh ke pohon panggilan. Jika Anda perlu menangkap level log, Anda bisa melempar pengecualian khusus.
Melakukan panggilan ke metode yang sudah diinstrumentasi untuk logging.
sumber
Apakah benar-benar diperlukan untuk memisahkan logging Anda dari logika bisnis Anda? Pembalakan yang dilakukan sesuai dengan logika bisnis yang ditulis dan karenanya masuk akal untuk berada di kelas / fungsi yang sama. Lebih penting lagi, ini membantu pembacaan kode yang lebih mudah.
Namun, jika Anda benar-benar ingin memisahkan pencatatan dari logika bisnis Anda, Anda harus mempertimbangkan untuk melempar pengecualian khusus dan menyerahkan pengecualian tersebut untuk pencatatan.
sumber
Tidak, tidak dalam c #
OP, jawaban untuk pertanyaan spesifik Anda adalah tidak, tidak dalam c #. Mungkin ada bahasa AOP lain yang lebih asli di luar sana, tetapi semua pendekatan untuk AOP dalam c # yang saya lihat hanya dapat menerapkan perilaku yang diduga dalam konteks titik bergabung , artinya harus ada aliran kontrol antara satu blok kode dan lain. Perilaku yang diharapkan tidak akan dieksekusi di tengah-tengah suatu metode, kecuali tentu saja dengan memanggil metode lain.
Anda bisa "apsect-ize" bit logging tertentu
Yang sedang berkata, Anda bisa mengekstrak kekhawatiran tertentu yang terlibat dalam penebangan, hanya saja tidak menulis log. Misalnya, cutpoint yang dieksekusi saat masuk ke metode dapat mengatur konteks logging dan output semua parameter input, dan saat keluar bisa menangkap pengecualian atau melakukan log ke penyimpanan permanen, hal semacam itu.
Menulis log bukan merupakan aspek
Saya akan menambahkan bahwa menulis log sebenarnya bukan masalah lintas sektoral. Setidaknya tidak debug logging. Bukti saya untuk ini adalah bahwa Anda tidak dapat menulis persyaratan lintas sektoral yang sepenuhnya menjelaskan apa yang akan dilakukan aspek ini - spesifik untuk setiap kasus, karena tujuan penulisan log adalah untuk mencerminkan apa yang terjadi dengan logika, dan logika dalam setiap metode harus cukup unik (lihat KERING ).
Dengan kata lain, ada ketergantungan logis yang tidak dapat dipisahkan antara penulisan log dan hal-hal yang sedang ditulis. Anda tidak dapat menggeneralisasikannya.
Tapi audit itu
Jika Anda memiliki semacam persyaratan logging fungsional (mis. Audit logging untuk mendukung persyaratan non-repudiation ) maka beberapa orang akan berdebat (dan saya akan setuju) bahwa jika Anda menemukan diri Anda perlu menjalankan penulisan log ini di tengah-tengah suatu metode, Anda belum menyusun kode dengan cara yang konsisten dengan pemikiran berorientasi aspek. Jika ini terjadi, Anda harus mengekstrak kode menjadi metode terpisah hingga Anda mendapatkan tingkat rincian yang Anda butuhkan.
sumber