دلفي الاستكشاف المتعمق - دليل تطبيق CodeSite
على الرغم من أن دلفي توفر لنا وظائف تصحيح أخطاء قوية للغاية، إلا أن العثور على الأخطاء لا يزال مهمة شاقة عادةً ما يكون الوقت الذي نقضيه في كتابة التعليمات البرمجية وتصحيح الأخطاء هو نفسه تقريبًا، وربما يكون أكثر من ذلك. من أجل تقليل الهدر غير الضروري للوقت والطاقة، ما زلنا في بعض الأحيان بحاجة إلى مساعدة أدوات تصحيح الأخطاء الاحترافية لتحسين كفاءة قفل الأخطاء. في هذا المقال سنقدم أداة تصحيح الأخطاء الشهيرة CodeSite PRO 2.0 (فازت بالمركز الثاني في جائزة اختيار قراء Delphi Informant لعام 2000 لأفضل أداة تصحيح أخطاء). موقعها الرسمي هو www.raize.com. تتمثل الوظيفة الرئيسية لـ CodeSite في السماح للمطورين باستخدام التعليمات البرمجية لإرسال تفاصيل وقت التشغيل إلى أجهزة استقبال خاصة لمزيد من التحليل. وبشكل أكثر دقة، من خلال فئة TCodeSite التي تنفذها CodeSite، يمكننا حزم معلومات وقت التشغيل وإرسالها إلى CodeSite Dispatcher (موزع رسائل CodeSite)، والذي يمكنه توجيه هذه الرسائل إلى جهاز استقبال واحد أو أكثر للعرض. مستقبل الرسالة الافتراضي هو CodeSite Viewer. تنعكس كفاءة CodeSite في حقيقة أنها تختلف عن مربع حوار بسيط يعرض الرسائل أو تحدد نقاط توقف للتحقق من المتغيرات، وهي تشبه إلى حد كبير وظيفة سجل الأحداث (Event Log) التي تأتي مع دلفي وهو بلا شك أقوى من سجل الأحداث، وهو كثير، ورسائله مستدامة، أي أنه يمكن حفظها، مما يسهل التحليل بأثر رجعي. قبل تقديم الاستخدام المحدد لـ CodeSite، دعونا أولاً نلقي نظرة على مكوناته الثلاثة. كائن CodeSite كما ذكرنا سابقًا، يتم إرسال رسائل CodeSite من تطبيق قيد التشغيل باستخدام مثيل لفئة TCodeSite (المحددة في وحدة CSIntf). يمكننا ببساطة استدعاء أسلوب فئة TCodeSite المرسل. على سبيل المثال، يمكنك استخدام الأسلوب SendMsg الخاص بالكائن لإرسال رسالة سلسلة بسيطة. يطبق كائن TCodeSite عددًا كبيرًا من الأساليب لدعم إرسال أنواع مختلفة من المعلومات دون أي تحويل للبيانات. على سبيل المثال، تحتوي طريقة SendObject الخاصة بالكائن على معلمتين: إحداهما عبارة عن سلسلة الرسالة، والأخرى عبارة عن مرجع لمثيل الكائن. ستحصل هذه الطريقة على الكائن كافة السمات المنشورة، ثم تقوم بتجميع معلومات هذه السمات في رسائل CodeSite. مرسل CodeSite في معظم الحالات، سيتم تشغيل CodeSite Dispatcher بهدوء في منطقة علبة النظام. وتتمثل وظيفتها الوحيدة في توجيه رسائل CodeSite المرسلة من كائنات TCodeSite المختلفة إلى وجهاتها. افتراضيًا، يتم إرسال رسائل CodeSite إلى CodeSite Viewer. لا نحتاج حتى إلى تشغيل CodeSite Dispatcher لأنه سيتم تشغيله تلقائيًا بواسطة كائنات مثل TCodeSite. تحدد فئة TCodeSite خاصية DestinationDetails التي تسمح للمطورين بتكوين كيفية توجيه رسائل CodeSite المرسلة بواسطة CodeSite Dispatcher إلى وجهات مختلفة، مثل ملفات السجل. ولكن عادة لا توجد حاجة لتعديل هذه الخاصية. عارض CodeSite على الرغم من أن CodeSite يدعم إرسال الرسائل إلى أهداف مختلفة، إلا أنه في معظم الحالات يكون CodeSite Viewer هو هدف الإرسال الأساسي. حتى عند إرسالها إلى وجهات أخرى، مثل ملفات السجل أو جهاز آخر، يظل CodeSite Viewer هو الأداة الأساسية لعرض الرسائل وتحليلها. يتكون CodeSite Viewer من اللوحات الأربع التالية: قائمة الرسائل، وعارض الرسائل، ومكدس المكالمات، ولوحة Scratch. مساحة العمل الرئيسية لـ CodeSite Viewer هي قائمة الرسائل، والتي تُستخدم لعرض جميع الرسائل المرسلة إلى العارض أو الرسائل المحملة من ملفات السجل. يتم استخدام عارضي الرسائل لعرض المعلومات الإضافية المرتبطة بالرسائل. على سبيل المثال، إذا تم إرسال الرسالة الحالية بواسطة طريقة SendObject، فسيعرض عارض الرسائل القيم الحالية لجميع الخصائص المنشورة للكائن. تعرض لوحة مكدس الاستدعاءات عرض مكدس استنادًا إلى رسائل csmEnterMethod. تُستخدم لوحات الخدش لعرض المعلومات غير المستدامة. تعد لوحة Scratch مفيدة جدًا عندما نريد تتبع معلومات معينة ولكن لا نريد تسجيلها في سجل الرسائل، على سبيل المثال عندما نريد عرض عدد كبير من الرسائل المتكررة مثل الموضع الحالي للماوس. في هذا الوقت يمكننا استخدام طريقة WritePoint لكائن TCodeSite وتحديد معلمة Line ID لتحديد عدد أسطر لوحة الرسم المستخدمة لاستيعاب معلومات الماوس. دعونا نستخدم مثالًا بسيطًا لتوضيح كيفية إرسال رسالة إلى CodeSite Viewer من البرنامج: (1) قم بإنشاء مشروع جديد، ثم قم بتبديل لوحة المكونات إلى صفحة CodeSite (سيقوم CodeSite بتثبيت مكونين في النظام بعد تثبيت TCSGlobalObject وTCSObject). حدد مكون TCSGlobalObject وضعه في النموذج. يوفر مكون TCSGlobalObject تفاعل وقت التصميم مع كائن TCodeSite العمومي (تتم تهيئة TCodeSite العمومي في وحدة CSInft). (2) أضف زرًا، ثم اكتب التعليمة البرمجية التالية في حدث OnClick الخاص به: //CodeSite هو كائن TCodeSite العام CodeSite.SendMsg('الرسالة الأولى لـCodeSite'); (3) قم بتجميع هذا البرنامج البسيط وتشغيله. انقر فوق الزر بعد التشغيل، وسيتم تشغيل CodeSite Dispatcher وCodeSite Viewer. وفي نفس الوقت ستظهر لك الرسائل التي يرسلها البرنامج في قائمة رسائل CodeSite Viewer (ملاحظة: لا نحتاج إلى تشغيل CodeSite Dispatcher وCodeSite Viewer قبل تشغيل البرنامج، لأن كائن TCodeSite سيبدأ تشغيلهما تلقائيًا عند تشغيله). يحتاج إلى إرسال الرسائل). تظهر نتائج التشغيل في الشكل 4.38 أدناه:
(4) بعد ذلك، أوقف البرنامج وأضف الكود التالي في عملية معالجة الحدث OnClick: CodeSite.SendObject('Form1', Form1); (5) أعد ترجمة البرنامج وتشغيله، وانقر فوق الزر مرة أخرى، هذه المرة ستكون كذلك في CodeSite Viewer رأيت رسالتين. تتضمن الرسالة المطابقة لـ Form1 معلومات كائن Form1. (6) لرؤية معلومات الكائن المرتبطة بـ Form1، حدد أمر قائمة CodeSite Viewer View|Inspector لعرض لوحة جديدة على الجانب الأيمن من قائمة الرسائل، حيث يتم عرض السمات المنشورة لـ Form1، كما هو موضح في الشكل 4.39 أدناه:
(7) أوقف البرنامج مرة أخرى، ثم قم بتعديل التعليمات البرمجية في عملية OnClick كما يلي: CodeSite.EnterMethod('Button1Click'); CodeSite.SendMsg('CodeSite's first message'); CodeSite.SendObject('Form1', Form1 ) ; (8) هذه المرة عندما نقوم بتشغيل البرنامج والنقر على الزر، سنرى أن رسائل "CodeSite's First message" و"Form1" قد تم وضع مسافة بادئة بين رسائل "Button1Click"، كما هو موضح في الشكل 4.40 أدناه:
من خلال إضافة استدعاءات إلى طريقتي EnterMethod وExitMethod، يمكننا إنشاء سجل لتسجيل وقت استدعاء الطريقتين. بعد النظر إلى الأمثلة، سنجد أن وظيفة CodeSite قوية جدًا. يمكننا إنشاء معلومات مفصلة للغاية بمجرد إضافة بعض البيانات إلى البرنامج وعرضها في مخططات حية من خلال CodeSite Viewer. بعد ذلك، دعونا نتحدث عن تقنية التطبيقات المتقدمة في CodeSite. إرسال رسائل إلى ملفات السجل سيكون لكل برنامج أخطاء أكثر أو أقل، إذا لم يحدث ذلك في هذا الوقت، فسيحدث في ذلك الوقت، وإذا لم يحدث في وقت قصير، فقد يحدث بعد وقت طويل. في بعض الأحيان يحدث ذلك مرارا وتكرارا، وأحيانا يحدث ذلك عن طريق الصدفة. إذا أخبرك شخص أن البرامج التي يكتبها تعمل دون أي مشاكل في أي وقت، فهو يكذب. وبسبب الطبيعة العرضية والخفية للأخطاء على وجه التحديد، يصعب علينا في كثير من الأحيان تكرار الأخطاء التي أرسلها المستخدمون، مما يخلق عائقًا كبيرًا أمامنا لتصحيح أخطاء البرنامج والعثور على سبب المشكلة، ويمكن لـ CodeSite إرسال الرسائل لتسجيل الملفات، وهذا يسهل على المستخدمين الإبلاغ عن الأخطاء، حيث أنهم يحتاجون فقط إلى إرسال ملف المعلومات الذي تم إنشاؤه أثناء وقت التشغيل. وفي المقابل، سيصبح عملنا في تصحيح أخطاء البرنامج أسهل، ويمكننا استخدام CodeSite Viewer لتحليل سبب الخطأ وموقعه بشكل بديهي. لتغيير وجهة إرسال الرسالة، يمكننا القيام بذلك عن طريق تعيين خاصية DestinationDetails لكائن TCodeSite. تتطلب هذه الميزة تثبيت CodeSite Dispatcher على جهاز العميل، وهو جزء قابل للتوزيع مجانًا من CodeSite. لا تزال العملية المحددة أدناه تعتمد على المثال المذكور سابقًا: (1) أضف التعليمات البرمجية التالية إلى حدث OnCreate للنموذج: CodeSite.DestinationDetails := 'File[Path=C:/FirstLog.csl]' (2 ) قم بتجميع البرنامج وتنفيذه، هذه المرة بعد النقر فوق الزر، لم تعد الرسالة تُرسل إلى CodeSite Viewer، بل إلى ملف FirstLog.csl الموجود على محرك الأقراص C. (3) استخدم CodeSite Viewer لتحميل ملف FirstLog.csl هذه المرة نعرض رسائل CodeSite المحفوظة كما كان من قبل. (4) إذا أردنا إرسال رسائل إلى CodeSite Viewer وملفات السجل في نفس الوقت، فما عليك سوى تعديل الكود السابق إلى: CodeSite.DestinationDetails := 'Viewer,File[Path=C:/FirstLog.csl]'; - البيانات المخصصة على الرغم من أن فئة TCodeSite توفر عددًا كبيرًا من الطرق لمعالجة أنواع البيانات المختلفة، فقد نحتاج أحيانًا إلى إرسال معلومات البيانات بتنسيق مخصص معين. ولتحقيق هذه الغاية، تحدد فئة TCodeSite طريقة SendCustomData، التي تدعم إرسال أي نوع بيانات وتنسيق البيانات وفقًا لمنسق مخصص حتى يتمكن عارض CodeSite من عرض البيانات بشكل صحيح. نحتاج أولاً إلى إنشاء فئة فرعية لكائن TCSFormatter، ثم تحميل أساليب FormatData وInspectorType وTypeName الخاصة بالكائن. ثم قم باستدعاء كائن إدارة كائنات CodeSite CSObjectManager لتسجيل فئة فرعية TCSFormatter جديدة. بالإضافة إلى ذلك، نحتاج أيضًا إلى استدعاء الأسلوب RegisterCustomFormat لتسجيل نوع رسالة جديد. ما يلي هو مثال للتطبيق العملي. يتم تطبيق منسق مخصص لنوع السجل TCSEmployee.pas: واجهة CSEmployee تستخدم Windows، Graphics، CSIntf؛ ، في قسم الاستخدامات يضيف مرجعًا إلى وحدة CSIntf. الخطوة الثانية هي تحديد ثوابت جديدة لنوع رسالة CodeSite لكل منسق. لقد حددنا ثابتين أعلاه. لاحظ أن الثوابت يجب أن تكون أكبر من csmUser، ولكن ليس أكبر من 32000. اكتب TCSEmployee = اسم العائلة: سلسلة؛ العنوان: سلسلة؛ المدينة: الرمز البريدي: سلسلة؛ Boolean end؛ السجل أعلاه هو نوع البيانات المخصصة التي نريد إرسالها. TCSEmployeeSummaryFormatter = class( TCSFormatter) InspectorType: TCSInspectorType; فيما يلي تعريفات فئتين منسقتين مخصصتين. سيقوم المنسق الأول بتنسيق سجل TCSEmployee في تنسيق نص، وسيقوم المنسق الثاني بتنسيق سجل TCSEmployee في نمط الشبكة. يستخدم التنفيذ SysUtils {============================} {= = أساليب TCSEmployeeSummaryFormatter ==} {============================================== ==} وظيفة TCSEmployeeSummaryFormatter .InspectorType: TCSInspectorType النتيجة: = itStockStringList؛ الخطوة الأولى في تنفيذ منسق مخصص هي تحديد نوع العارض المضمن الذي سيتم استخدامه لعرض البيانات المنسقة. في هذه الحالة، يتم استخدام عارض قائمة السلاسل. سيتم استخدام نوع العارض بواسطة الأسلوب FormatData. الإجراء TCSEmployeeSummaryFormatter.FormatData( var Data ); var EmpRec: TCSEmployee; begin EmpRec := TCSEmployee( Data ); AddLine( EmpRec.FirstName + ' ' + EmpRec.LastName ); ', ' + EmpRec.State + ' ' + EmpRec.ZipCode ); AddLine( ''); AddLine( 'الهاتف:' + EmpRec.PhoneNumber ); AddLine( 'تاريخ التوظيف:' + DateToStr( EmpRec.HireDate ) ); م'، [EmpRec.Salary ] ) ); AddLine( '' ); ' + IntToStr( EmpRec.VacationDays ) ); AddLine( 'أيام مرضية: ' + IntToStr( EmpRec.SickDays ) ); إذا كان EmpRec.Manager ثم AddLine( 'Manager: Yes' ) else AddLine( 'Manager: No' ); يعد أسلوب FormatData هو الجزء الأساسي. لاحظ أن معلمة البيانات التي تم تمريرها إلى أسلوب FormatData هي معلمة متغيرة غير مكتوبة. وهذا يعني أن هذه المعلمة يمكن أن تكون من أي نوع بيانات، ومن خلال عملية تسجيل التنسيق، يمكننا التأكد من تعيين النوع القسري إلى سجل بيانات مخصص دون أخطاء التحويل. بعد تحويل نوع البيانات، يمكننا تنسيق البيانات هنا نستخدم طريقة AddLine للفئة الأساسية TCSFormatter لإضافة خطوط فاصلة بين السلاسل للتنسيق. دالة TCSEmployeeSummaryFormatter.TypeName: string; begin النتيجة:= 'TCSEmployee'; يعد التحميل الزائد لأسلوب TypeName اختياريًا، ولكن يمكننا استخدامه عادةً لإرجاع السلسلة التي تظهر في قائمة الرسائل. {========================= طرق TCSEmployeeDetailsFormatter == } {==========================} الدالة TCSEmployeeDetailsFormatter.InspectorType: TCSInspectorType ; نتيجة البداية := itStockGrid; بالنسبة لمنسق تفاصيل الموظفين، سيتم استخدام عارض الشبكة المسمى لعرض البيانات: الإجراء TCSEmployeeDetailsFormatter.FormatData( var Data ); var EmpRec: TCSEmployee; begin EmpRec := TCSEmployee( Data ); ; AddNameValuePair( 'Address', EmpRec.Address ); AddNameValuePair( 'City', EmpRec.City ); AddNameValuePair( 'State', EmpRec.State ); AddNameValuePair( 'ZipCode', EmpRec.ZipCode ); EmpRec.PhoneNumber ); 'HireDate', EmpRec.HireDate ); AddNameValuePair( 'Salary', Format( '%m', [ EmpRec.Salary ] ) ); AddNameValuePair( 'VacationDays', EmpRec.VacationDays ); ); EmpRec.Manager ); هنا من أجل تنسيق البيانات في عارض الشبكة، نستخدم طريقة AddNameValuePair. دالة TCSEmployeeDetailsFormatter.TypeName: string; begin النتيجة:= 'TCSEmployee'; يتم استخدام الإجراءين التاليين لتغليف استدعاءات أسلوب SendCustomData هنا، يتم استدعاء CodeSite لمثيل كائن TCodeSite: {===== =================} إجراء CSSendEmployeeSummary ( const الرسالة: سلسلة؛ EmpRec: TCSEmployee ); begin CodeSite.SendCustomData( csmEmployeeSummary, Msg, EmpRec ); وأخيرًا، لا تنس استدعاء الأسلوب CSObjectManager.RegisterCustomFormatter لتسجيل المنسق في CodeSite Object Manager. التهيئة CSObjectManager.RegisterCustomFormatter( csmEmployeeSummary, TCSEmployeeSummaryFormatter ); CSObjectManager.RegisterCustomFormatter( csmEmployeeDetails, TCSEmployeeDetailsFormatter );