मैं लॉगिंग facades का उपयोग करता था जैसे कि Common.Logging (यहां तक कि अपनी खुद की CutEdge.Logging पुस्तकालय को छिपाने के लिए ), लेकिन आजकल मैं डिपेंडेंसी इंजेक्शन पैटर्न का उपयोग करता हूं और इससे मुझे अपने (सरल) अपवर्तन के पीछे लॉगर्स को छिपाने की अनुमति मिलती है जो दोनों निर्भरता का पालन करता है। उलटा सिद्धांत और इंटरफ़ेस अलगाव सिद्धांत(आईएसपी) क्योंकि इसमें एक सदस्य है और क्योंकि इंटरफ़ेस मेरे अनुप्रयोग द्वारा परिभाषित किया गया है; बाहरी पुस्तकालय नहीं। इस ज्ञान को कम करना कि आपके आवेदन के मुख्य हिस्सों में बाहरी पुस्तकालयों के अस्तित्व के बारे में बेहतर है; यहां तक कि अगर आपके पास अपनी लॉगिंग लाइब्रेरी को बदलने का कोई इरादा नहीं है। बाहरी पुस्तकालय पर कठिन निर्भरता आपके कोड का परीक्षण करना कठिन बना देती है, और आपके एप्लिकेशन को एक ऐसे एपीआई के साथ जोड़ देती है, जिसे कभी आपके आवेदन के लिए विशेष रूप से तैयार नहीं किया गया था।
यह वह अमूर्त है जो अक्सर मेरे अनुप्रयोगों में दिखता है:
public interface ILogger
{
void Log(LogEntry entry);
}
public enum LoggingEventType { Debug, Information, Warning, Error, Fatal };
// Immutable DTO that contains the log information.
public class LogEntry
{
public readonly LoggingEventType Severity;
public readonly string Message;
public readonly Exception Exception;
public LogEntry(LoggingEventType severity, string message, Exception exception = null)
{
if (message == null) throw new ArgumentNullException("message");
if (message == string.Empty) throw new ArgumentException("empty", "message");
this.Severity = severity;
this.Message = message;
this.Exception = exception;
}
}
वैकल्पिक रूप से, इस अमूर्त को कुछ सरल विस्तार विधियों (इंटरफ़ेस को संकीर्ण रहने और आईएसपी का पालन करने की अनुमति देने) के साथ बढ़ाया जा सकता है। यह इस इंटरफ़ेस के उपभोक्ताओं के लिए कोड को बहुत सरल बनाता है:
public static class LoggerExtensions
{
public static void Log(this ILogger logger, string message) {
logger.Log(new LogEntry(LoggingEventType.Information, message));
}
public static void Log(this ILogger logger, Exception exception) {
logger.Log(new LogEntry(LoggingEventType.Error, exception.Message, exception));
}
// More methods here.
}
चूँकि इंटरफ़ेस में केवल एक विधि है, आप आसानी से एक ILogger
कार्यान्वयन बना सकते हैं जो log4net को , Serilog , Microsoft.Extension.Logging , NLog या किसी अन्य लॉगिंग लाइब्रेरी को प्रॉक्सी करता है और इसे कक्षाओं में रखने के लिए अपने DI कंटेनर को कॉन्फ़िगर करता है:ILogger
उनके उनके पास हैं। निर्माता।
ध्यान दें कि एक एकल विधि के साथ एक अंतरफलक के शीर्ष पर स्थिर विस्तार विधियाँ कई सदस्यों के साथ एक अंतरफलक होने से काफी अलग है। विस्तार विधियाँ केवल सहायक विधियाँ हैं जो एक LogEntry
संदेश बनाती हैं और इसे ILogger
इंटरफ़ेस पर एकमात्र विधि के माध्यम से पारित करती हैं । विस्तार विधियां उपभोक्ता के कोड का हिस्सा बन जाती हैं; अमूर्तन का हिस्सा नहीं है। न केवल यह विस्तार विधियों को अमूर्तता, विस्तार के तरीकों और ए को बदलने की आवश्यकता के बिना विकसित करने की अनुमति देता हैLogEntry
जब हमेशा उस लकड़हारे को ठूंसा / मजाक किया जाता है, तब भी कंस्ट्रक्टर को निष्पादित किया जाता है। यह टेस्ट सूट में चलने पर लकड़हारे को कॉल की शुद्धता के बारे में अधिक निश्चितता देता है। एक-सदस्यीय इंटरफ़ेस परीक्षण को बहुत आसान बनाता है; कई सदस्यों के साथ अमूर्त होने से कार्यान्वयन (जैसे कि नकली, एडेप्टर और डेकोरेटर) बनाना मुश्किल हो जाता है।
जब आप ऐसा करते हैं, तो शायद ही कभी कुछ स्थिर अमूर्तता की आवश्यकता होती है जो लॉगिंग facades (या किसी अन्य पुस्तकालय) की पेशकश कर सकते हैं।