डेटा सिंक्रोनाइज़र। डेवलपर को ध्यान दें

काम पर और रोजमर्रा की जिंदगी में, हमें अक्सर विभिन्न प्रकार के डेटा सिंक्रनाइज़ेशन से निपटना पड़ता है। आप कंप्यूटर के साथ अपने फोन की फ़ाइलों और फ़ोल्डरों को सिंक्रनाइज़ करते हैं, संस्करण नियंत्रण प्रणालियों में सामान्य क्रियाएं करते हैं, संपर्कों, मेल संदेशों और दस्तावेजों को सिंक्रनाइज़ करने के लिए विभिन्न ऑनलाइन सेवाओं का उपयोग करते हैं, और अक्सर यह भी नहीं सोचते कि यह प्रक्रिया किसी विशेष मामले में कैसे लागू की जाती है।



यदि आप अपना खुद का सिंक्रनाइज़र लिखने का फैसला करते हैं, तो सबसे अधिक संभावना है कि आप कई सवालों के जवाब देंगे। इस लेख में हम इस तरह के एक घटक को लिखने का अनुभव साझा करेंगे और इसके लिए आवश्यकताओं पर विचार करेंगे। ये आवश्यकताएं उन सभी प्रकार की इच्छाओं पर आधारित होती हैं जो हमें XtraScheduler अनुसूचक ईवेंट सिंक्रोनाइज़र का उपयोग करने के लिए उपयोगकर्ताओं और वास्तविक परिदृश्यों से मिली थीं । इसलिए, कोड उदाहरण के रूप में, हम निर्दिष्ट उत्पाद से कोड के टुकड़े देंगे।



सबसे पहले, हम यह निर्धारित करते हैं कि कौन सी वस्तुएं सिंक्रनाइज़ेशन प्रक्रिया में भाग लेंगी।

ये दो डेटा सेट (स्रोत और लक्ष्य / अंतिम) और एक सिंक्रनाइज़र है जो इन सेटों पर कई ऑपरेशन करता है, जिसके परिणामस्वरूप लक्ष्य सेट को लागू होने वाले परिदृश्य के अनुसार बदलना चाहिए।



सिंक्रोनाइज़र ऑब्जेक्ट


सिंक्रोनाइज़ेशन स्क्रिप्ट यह निर्धारित करेगी कि आपके सिंक्रोनाइज़र की कार्यक्षमता क्या होगी। यदि सिंक्रनाइज़ेशन का अर्थ केवल एक "मुख्य" कॉपी है और किसी अन्य के साथ सामग्री को पूरी तरह से बदलकर प्रदर्शन किया जाएगा, तो आयातक / निर्यातक प्रकार का एक सरल संस्करण उपयुक्त है। यदि आप स्वतंत्र रिकॉर्ड के सेट को सिंक्रनाइज़ करने की योजना बनाते हैं, तो आपको सिंक्रोनाइज़र का अधिक जटिल कार्यान्वयन करना होगा।



आधार वर्ग


एक बेस सिंक्रोनाइज़र वर्ग बनाएं जो सभी वंशजों के लिए सामान्य व्यवहार और विधियों, गुणों और घटनाओं के इंटरफ़ेस को परिभाषित करता है। हम ऐसे वर्ग को कहेंगे, उदाहरण के लिए, SynchronizerBase। ऐसा वर्ग वांछित अनुक्रम में बुनियादी आवश्यक तुल्यकालन क्रियाओं को करने के लिए अमूर्त विधियों की कॉल के एक कड़ाई से परिभाषित क्रम को परिभाषित कर सकता है। विरासत द्वारा कार्यशीलता का विस्तार किया जाएगा। बेस क्लास होने से आप कोड डुप्लीकेशन से मुक्त हो जाते हैं। आंतरिक संरचना और गुणों को शुरू करने जैसे सामान्य संचालन को इस वर्ग में एक बार लागू किया जा सकता है।



इस दृष्टिकोण का एक अतिरिक्त लाभ यह तथ्य होगा कि आपको बाद में लागू वारिसों के लिए एक सुसंगत एपीआई प्राप्त होगा।



public abstract class SynchronizerBase { //... protected SynchronizerBase(StorageBase storage) {...} public event ExchangeExceptionEventHandler OnException; protected internal abstract void SynchronizeCore(); public virtual void Terminate() {...} public virtual void Synchronize() { Storage.BeginUpdate(); try { ResetTermination(); SynchronizeCore(); } finally { Storage.EndUpdate(); } } }
      
      







कर्तव्यों का विभाजन


डेटा सेट के साथ काम करने के परिदृश्यों के आधार पर, आप संगत सिंक्रोबाइज़रबेस वंशजों को लागू कर सकते हैं जो स्क्रिप्ट में निर्धारित कार्यों के अनुक्रम को पूरा करने में "सक्षम" हैं, जो पहले से जानते हुए सेट "मुख्य" है। इस तरह के विशेष वर्गों को स्थापित करने और केवल एक का उपयोग करने की तुलना में उपयोग करना बहुत आसान होगा जो "एक बार में सब कुछ जानता है।



इस प्रकार, आप कई वंशज बना सकते हैं, उदाहरण के लिए, ImportSynchronizer और ExportSynchronizer, जो प्रत्येक परिदृश्य के लिए मूल सिंक्रनाइज़ेशन तर्क को लागू करते हैं। यदि आप भविष्य में विभिन्न डेटा सेट के लिए अपने विशिष्ट वंशजों को लागू करने की योजना बना रहे हैं तो ये कक्षाएं अमूर्त रह सकती हैं।



उदाहरण के लिए, XtraScheduler में हमें निम्नलिखित बेस क्लास स्कीम मिली:







उप-विभाजक एल्गोरिदम


सिंक्रोनाइज़र ऑब्जेक्ट को बहुत अधिक लोड नहीं करने के लिए, यह सिंक्रोनाइज़ेशन एल्गोरिदम के कार्यान्वयन को सिंक्रोनाइज़ेशन के इंटरफ़ेस से ही अलग करके आर्किटेक्चर को व्यवस्थित करने के लिए समझ में आता है। इन ऑब्जेक्ट्स के बीच इंटरैक्शन स्थापित करने के लिए भूलकर, सिंक्रोनाइज़र वर्ग में एक उपवर्ग का चयन करें।



 public class ImportSynchronizeManager : ImportManager { public ImportSynchronizeManager(AppointmentExchanger synchronizer) : base(synchronizer) { } protected internal override void PerformExchange() { Appointments.BeginUpdate(); try { PrepareSynchronization(); SynchronizeAppointments(); DeleteNonSynchronizedAppointments(); } finally { Appointments.EndUpdate(); } } } public class ExportSynchronizeManager : ExportManager { public ExportSynchronizeManager(AppointmentExchanger synchronizer) : base(synchronizer) { } protected internal override void PerformExchange() { PrepareSynchronization(); SynchronizeOutlookAppointments(); CreateNewOutlookAppointments(); } }
      
      







डेटासेट वस्तुओं पर संचालन


सिंक्रनाइज़ेशन परिदृश्य के आधार पर, डेटा सेट को विभिन्न तरीकों से संशोधित किया जा सकता है। लेकिन, एक नियम के रूप में, सेट ऑब्जेक्ट्स के साथ सभी क्रियाएं तीन मुख्य क्रियाओं में कम हो जाती हैं:



ऊपर वर्णित सभी ऑपरेशन निम्न तालिका में कम किए जा सकते हैं:







वर्णित क्रियाओं को आपके सिंक्रनाइज़ेशन के प्रत्येक वारिस में एक या किसी अन्य रूप में लागू किया जाना चाहिए। इस मामले में, महत्वपूर्ण बिंदु को ध्यान में रखना आवश्यक है, जो डेटा की प्रतिलिपि को "मुख्य" माना जाता है। पसंद के आधार पर, स्रोत और लक्ष्य सेट स्थान बदल सकते हैं। यही कारण है कि ImportSynchronizer और ExportSynchronizer Classes डेटासेट्स पर विपरीत क्रियाएं करेंगे।



घटना का समर्थन


निस्संदेह, जब सेट ऑब्जेक्ट्स पर कोई कार्रवाई करते हैं, तो उपयोगकर्ता इन ऑब्जेक्ट्स को "ऑपरेशन से पहले" और "ऑपरेशन के बाद" एक्सेस करने में सक्षम होना चाहेगा। बेस क्लास में सिंक्रोनाइज़ और सिंक्रोनाइज़ किए गए इवेंट की एक जोड़ी व्यवस्थित करें।



SynchronizingEventArgs और SynchronizedEventArgs ईवेंट हैंडलर के लिए तर्कों को परिभाषित करें और सिंक्रनाइज़ किए गए सेट से संबंधित ऑब्जेक्ट्स के लिए फ़ील्ड और गुण जोड़ें। मामले में जब बेस क्लास में तुरंत ऐसा करना असंभव है, तो तर्क की विरासत का उपयोग करें और वारिस में लापता गुणों को बनाएं।



 public class AppointmentEventArgs : EventArgs { public AppointmentEventArgs(Appointment apt) { } public Appointment Appointment { get { ... } } } public class AppointmentCancelEventArgs : AppointmentEventArgs { public AppointmentCancelEventArgs(Appointment apt) : base(apt) { } public bool Cancel { get { ... } } } public class AppointmentSynchronizingEventArgs : AppointmentCancelEventArgs { public AppointmentSynchronizingEventArgs(Appointment apt) : base(apt) { } public SynchronizeOperation Operation { get { ... } } } public class OutlookAppointmentSynchronizingEventArgs : AppointmentSynchronizingEventArgs { public OutlookAppointmentSynchronizingEventArgs(Appointment apt, _AppointmentItem olApt) : base(apt) { } public _AppointmentItem OutlookAppointment { get { ... } } }
      
      







अपवादों को संभालने के लिए घटनाओं की आवश्यकता पर विचार करें। उदाहरण के लिए, आप OnException घटना को लागू कर सकते हैं और वहां प्राप्त अपवादों को पुनर्निर्देशित कर सकते हैं। उपयोगकर्ता को यह तय करने दें कि क्या अपवाद होने के बाद सिंक्रनाइज़ेशन प्रक्रिया को जारी रखना है या नहीं। सभी आवश्यक जानकारी के साथ घटना के तर्क को पूरा करें।



 iCalendarImporter importer; //... importer.OnException += new ExchangeExceptionEventHandler(importer_OnException); void importer_OnException(object sender, ExchangeExceptionEventArgs e) { iCalendarParseExceptionEventArgs args = e as iCalendarParseExceptionEventArgs; if (args != null) { ShowErrorMessage(String.Format("Cannot parse line {0} with text '{1}'", args.LineIndex, args.LineText)); } else ShowErrorMessage(e.OriginalException.Message); e.Handled = true; // prevent this exception from throwing } }
      
      







डेटा सुरक्षा


सेट ऑब्जेक्ट्स पर प्रत्येक ऑपरेशन को रद्द करने की क्षमता का समर्थन करें। इसे SynchronizingEventArgs ईवेंट के तर्कों में रद्द गुण जोड़कर किया जा सकता है।



सुनिश्चित करें कि यह दो स्वतंत्र डेटा सेट "मर्जिंग" के परिदृश्य के लिए काम में आने के लिए निश्चित है, जब यह सिंक्रनाइज़ेशन, पहले एक दिशा में और फिर दूसरे में सभी हटाने के कार्यों को रद्द करने के लिए समझ में आता है।



 AppointmentImportSynchronizer synchronizer; //... synchronizer.AppointmentSynchronizing += new AppointmentSynchronizingEventHandler(synchronizer_AppointmentSynchronizing); void synchronizer_AppointmentSynchronizing(object sender, AppointmentSynchronizingEventArgs e) { // ... if (ShouldCancelOperation) e.Cancel = true; }
      
      







सभी ऑब्जेक्ट हेरफेर परिदृश्यों को कवर करना


वस्तु पर प्रस्तावित "डिफ़ॉल्ट" कार्रवाई को रद्द करने के लिए न केवल स्थिति पर विचार करें, बल्कि एक अन्य संभावित ऑपरेशन को सक्षम करने के लिए भी।



उदाहरण के लिए, तर्कों के लिए वैकल्पिक SynchronizeOperation {क्रिएट, रिप्लेस, डिलीट} प्रॉपर्टी जोड़ें और उपयोगकर्ता को वांछित मान निर्दिष्ट करें। इस प्रकार, आप ऑब्जेक्ट को मूल सेट से कॉपी के साथ बदलने के बजाय लक्ष्य डेटा सेट पर हटा सकेंगे।



यह दृष्टिकोण डेटासेट में "संपादित संघर्ष" को अधिक सटीक रूप से संभालना संभव बनाता है।



 void synchronizer_AppointmentSynchronizing(object sender, AppointmentSynchronizingEventArgs e) { switch (e.Operation) { case SynchronizeOperation.Replace: if (ShouldDeleteInsteadReplace.Checked) e.Operation = SynchronizeOperation.Delete; break; }
      
      







यूआई तत्व


सिंक्रनाइज़र को डिज़ाइन करने का प्रयास करें ताकि यह संदेश, संवाद और अन्य दृश्य तत्वों के प्रदर्शन का उपयोग न करे। क्योंकि हमेशा की तरह एक उपयोगकर्ता है जिसे आपके घटक का उपयोग करने की आवश्यकता होगी, एप्लिकेशन से बनाई गई स्ट्रीम में सिंक्रनाइज़ेशन का प्रदर्शन करना या, उदाहरण के लिए, एक विशेष सेवा से।



डेटा कैशिंग


कभी-कभी यह सिंक्रनाइज़ेशन में अपनी वस्तुओं को संग्रहीत करके सेट किए गए डेटा को लोड करने के लिए समझ में आता है। यह तब समझ में आता है जब वास्तविक डेटा सेट पर बार-बार कॉल से बचने के लिए यह वांछनीय है। इसके अलावा, तुल्यकालन प्रक्रिया के दौरान, लक्ष्य डेटा सेट बदल सकता है, जो संभावित रूप से सिंक्रोनाइज़र कोड से इस सेट पर पुनरावृत्ति से जुड़ी समस्याओं में खुद को प्रकट कर सकता है।



डेटासेट परिमाणीकरण


जल्दी या बाद में, उपयोगकर्ता पूरे सेट को सिंक्रनाइज़ नहीं करना चाहेगा, लेकिन इसका केवल एक हिस्सा, उदाहरण के लिए, समय अंतराल या एक विशिष्ट पैरामीटर द्वारा।



समाधान उपयोगकर्ता को उनके प्रदाता को "पर्ची" करने की क्षमता के साथ एक स्रोत डेटा प्रदाता लिखना होगा, जो उनके तर्क को निर्धारित करता है। इस मामले में, सिंक्रनाइज़र को सीधे डेटा प्राप्त नहीं करना चाहिए, लेकिन प्रदाता के माध्यम से। इस मामले में, आपको सिंक्रोनाइज़र के अंदर ऊपर वर्णित डेटा कैशिंग का उपयोग करना होगा।



 void DoFilteredImport() { OutlookImport importer = new OutlookImport(this.schedulerStorage1); TimeInterval interval = CalculateCurrentWeekInterval(); ParameterizedCalendarProvider provider = new ParameterizedCalendarProvider(interval); importer.SetCalendarProvider(provider); importer.Import(System.IO.Stream.Null); }
      
      







प्रक्रिया पूरी हो रही है


उपयोगकर्ता के अनुरोध पर सिंक्रनाइज़ेशन प्रक्रिया को पूरा करने पर विचार करें। उदाहरण के लिए, आधार वर्ग SynchronizerBase में टर्मिनेट विधि प्राप्त करें। इस तरह के एक फ़ंक्शन उपयोगी हो सकता है जब बड़े डेटा सेट के सिंक्रनाइज़ेशन के दौरान कोई अपवाद होता है या सेट ऑब्जेक्ट कुछ शर्तों को पूरा नहीं करता है और आगे निष्पादन को तुरंत बाधित करना आवश्यक है। इस मामले में, उपयोगकर्ता को अब प्रक्रिया के अंत का इंतजार नहीं करना होगा।



 void synchronizer_OnException(object sender, ExchangeExceptionEventArgs e) { // ... AppointmentImportSynchronizer synchronizer = (AppointmentImportSynchronizer)sender; synchronizer.Terminate(); e.Handled = true; }
      
      







तानाना


ऐसा हो सकता है कि उपयोगकर्ता आपके घटक द्वारा सिंक्रनाइज़ किए गए के अलावा अन्य गुणों को सिंक्रनाइज़ करना चाहता है। कस्टम गुण या ऑब्जेक्ट सेट करने के स्तर पर इसे परिभाषित करने की क्षमता प्रदान करें और इसके लिए सभी आवश्यक एपीआई प्रदान करें।



 void exporter_AppointmentExporting(object sender, AppointmentExportingEventArgs e) { iCalendarAppointmentExportingEventArgs args = e as iCalendarAppointmentExportingEventArgs; AddEventAttendees(args.VEvent, “test@corp.com”); } private void AddEventAttendee(VEvent ev, string address) { TextProperty p = new TextProperty("ATTENDEE", String.Format("mailto:{0}", address)); p.AddParameter("CN", address); p.AddParameter("RSVP", "TRUE"); ev.CustomProperties.Add(p); }
      
      







उपयोगकर्ताओं को किसी भी कार्यक्षमता को ओवरराइड करने के लिए अपने सिंक्रोनाइज़र से विरासत में लेने की अनुमति दें। कक्षाओं और विधियों को डिजाइन करते समय इस पर विचार करें।



 public class MyOutlookImportSynchronizer : OutlookImportSynchronizer { public MyOutlookImportSynchronizer(SchedulerStorageBase storage) : base(storage) { } protected override OutlookExchangeManager CreateExchangeManager() { return new MyExchangeManager(); } }
      
      







सहायक वर्ग


सिंक्रोनाइज़र इनिशियलाइज़ेशन पैरामीटर प्राप्त करने के तरीके बनाएँ (उदाहरण के लिए, किसी विशिष्ट कैलेंडर पर दर्शाई गई निर्देशिका) या सिंक्रनाइज़ेशन के लिए आवश्यक कोई अन्य जानकारी। अधिक सुविधाजनक उपयोग के लिए, उन्हें अलग सहायक कक्षाओं में रखें या उन्हें सीधे घटक में उपलब्ध कराएं।



 public class OutlookExchangeHelper { public static string[] GetOutlookCalendarNames(); public static string[] GetOutlookCalendarPaths() ; public static List<OutlookCalendarFolder> GetOutlookCalendarFolders(); } public class OutlookUtils { public static _Application GetOutlookApplication(); public static void ReleaseOutlookObject(object obj); } public class iCalendarConvert { public static TimeSpan ToUtcOffset(string value); public static string FromUtcOffset(TimeSpan value) ; public static string UnescapeString(string str); }
      
      







हम वास्तव में आशा करते हैं कि उपरोक्त "टिप्स का संग्रह" आपको सिंक्रोनाइज़र लिखने से पहले आपको आवश्यक कार्यक्षमता की मात्रा निर्धारित करने में मदद करेगा और इसके कार्यान्वयन की प्रक्रिया में त्रुटियों से बचने के लिए संभव बना देगा।



All Articles