คู่มือแอปพลิเคชันการสำรวจเชิงลึกของ Delphi-CodeSite
แม้ว่า Delphi จะให้ฟังก์ชันการดีบักที่ทรงพลังอย่างยิ่งแก่เรา แต่การค้นหาจุดบกพร่องยังคงเป็นงานที่ลำบาก โดยปกติแล้วเวลาที่เราใช้ในการเขียนโค้ดและการดีบักโค้ดจะเท่ากันโดยประมาณ และอาจนานกว่านั้นด้วยซ้ำ เพื่อลดการเสียเวลาและพลังงานโดยไม่จำเป็น บางครั้งเรายังต้องการความช่วยเหลือจากเครื่องมือแก้ไขจุดบกพร่องแบบมืออาชีพเพื่อปรับปรุงประสิทธิภาพของการล็อคจุดบกพร่อง ในบทความนี้ เราจะแนะนำเครื่องมือแก้ไขจุดบกพร่องที่มีชื่อเสียง CodeSite PRo 2.0 (ได้รับรางวัลที่สองจากรางวัล Delphi Informant Readers' Choice Award ประจำปี 2000 สาขาเครื่องมือแก้ไขข้อบกพร่องที่ดีที่สุด) เว็บไซต์อย่างเป็นทางการของมันคือ www.raize.com หน้าที่หลักของ CodeSite คืออนุญาตให้นักพัฒนาใช้โค้ดเพื่อส่งรายละเอียดรันไทม์ไปยังผู้รับพิเศษเพื่อการวิเคราะห์เพิ่มเติม แม่นยำยิ่งขึ้นผ่านคลาส TCodeSite ที่ CodeSite นำมาใช้ เราสามารถจัดทำแพ็กเกจและส่งข้อมูลรันไทม์ไปยัง CodeSite Dispatcher (ผู้เผยแพร่ข้อความของ CodeSite) ซึ่งสามารถกำหนดเส้นทางข้อความเหล่านี้ไปยังผู้รับหนึ่งรายขึ้นไปเพื่อดูได้ ตัวรับข้อความเริ่มต้นคือ CodeSite Viewer ประสิทธิภาพของ CodeSite สะท้อนให้เห็นในความจริงที่ว่ามันแตกต่างจากกล่องโต้ตอบธรรมดาที่แสดงข้อความหรือการตั้งค่าเบรกพอยต์เพื่อตรวจสอบตัวแปร มันคล้ายกับฟังก์ชันบันทึกเหตุการณ์ (Event Log) ที่มาพร้อมกับ Delphi มากกว่า ไม่ต้องสงสัยเลยว่ามีประสิทธิภาพมากกว่าบันทึกเหตุการณ์ มีมากมายและข้อความนั้นยั่งยืนนั่นคือสามารถบันทึกได้ซึ่งอำนวยความสะดวกในการวิเคราะห์ย้อนหลัง ก่อนที่จะแนะนำการใช้งาน CodeSite โดยเฉพาะ ก่อนอื่นเรามาดูองค์ประกอบสามประการของ CodeSite กันก่อน ดังที่กล่าวไว้ข้างต้น การส่งข้อความ CodeSite ออกจากแอปพลิเคชันที่ทำงานอยู่สามารถทำได้โดยใช้อินสแตนซ์ของคลาส TCodeSite (กำหนดไว้ในหน่วย CSIntf) เราสามารถเรียกเมธอดของคลาส TCodeSite ได้ ผู้จัดส่ง ตัวอย่างเช่น คุณสามารถใช้เมธอด SendMsg ของวัตถุเพื่อส่งข้อความสตริงแบบธรรมดาได้ ออบเจ็กต์ TCodeSite ใช้เมธอดจำนวนมากเพื่อรองรับการส่งข้อมูลประเภทต่างๆ โดยไม่ต้องแปลงข้อมูลใดๆ ตัวอย่างเช่น เมธอด SendObject ของออบเจ็กต์มีพารามิเตอร์ 2 ตัว ตัวหนึ่งคือสตริงข้อความ และอีกตัวเป็นการอ้างอิงถึงอินสแตนซ์ของออบเจ็กต์ วิธีการนี้จะได้รับวัตถุ คุณลักษณะที่เผยแพร่ทั้งหมด และแพคเกจข้อมูลของคุณลักษณะเหล่านี้ลงในข้อความ CodeSite CodeSite Dispatcher ในกรณีส่วนใหญ่ CodeSite Dispatcher จะทำงานอย่างเงียบๆ ในพื้นที่ถาดระบบ ฟังก์ชันเดียวคือกำหนดเส้นทางข้อความ CodeSite ที่ส่งจากออบเจ็กต์ TCodeSite ต่างๆ ไปยังปลายทาง ตามค่าเริ่มต้น ข้อความ CodeSite จะถูกส่งไปยัง CodeSite Viewer เราไม่จำเป็นต้องเริ่ม CodeSite Dispatcher ด้วยซ้ำ เนื่องจากจะเริ่มทำงานโดยอัตโนมัติโดยออบเจ็กต์ เช่น TCodeSite คลาส TCodeSite กำหนดคุณสมบัติ DestinationDetails ที่ช่วยให้นักพัฒนากำหนดค่าวิธีที่ข้อความ CodeSite ที่ส่งถูกกำหนดเส้นทางโดย CodeSite Dispatcher ไปยังปลายทางต่างๆ เช่น ไฟล์บันทึก แต่โดยปกติแล้วไม่จำเป็นต้องแก้ไขคุณสมบัตินี้ CodeSite Viewer แม้ว่า CodeSite รองรับการส่งข้อความไปยังเป้าหมายที่แตกต่างกัน ในกรณีส่วนใหญ่ CodeSite Viewer จะเป็นเป้าหมายการส่งหลัก แม้ว่าจะส่งไปยังปลายทางอื่นๆ เช่น ไฟล์บันทึกหรือเครื่องอื่น CodeSite Viewer ยังคงเป็นเครื่องมือหลักในการดูและวิเคราะห์ข้อความ CodeSite Viewer ประกอบด้วยสี่แผงต่อไปนี้: รายการข้อความ โปรแกรมดูข้อความ Call Stack และแผง Scratch พื้นที่ทำงานหลักของ CodeSite Viewer คือรายการข้อความ ซึ่งใช้เพื่อแสดงข้อความทั้งหมดที่ส่งถึง 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's first message'); (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 ) ; CodeSite .ExitMethod('ปุ่ม1คลิก' ); (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 Viewer สามารถแสดงข้อมูลได้อย่างถูกต้อง ก่อนอื่น เราต้องสร้างคลาสย่อยของอ็อบเจ็กต์ TCSFormatter จากนั้นโอเวอร์โหลดเมธอด FormatData, InspectorType และ TypeName ของอ็อบเจ็กต์ จากนั้นเรียกอ็อบเจ็กต์ตัวจัดการอ็อบเจ็กต์ CodeSite CSObjectManager เพื่อลงทะเบียนคลาสย่อย TCSFormatter ใหม่ นอกจากนี้ เรายังต้องเรียกใช้เมธอด RegisterCustomFormat เพื่อลงทะเบียนประเภทข้อความใหม่ ต่อไปนี้เป็นตัวอย่างของการใช้งานจริง ฟอร์แมตเตอร์แบบกำหนดเองของประเภทเรกคอร์ด TCSEmployee ถูกนำไปใช้ในหน่วย CSEmployee.pas: หน่วย CSEmployee; อินเทอร์เฟซใช้ Windows, Graphics, CSIntf; const csmUser + 1; ในส่วนการใช้งานจะเพิ่มการอ้างอิงไปยังหน่วย CSIntf ขั้นตอนที่สองคือการกำหนดค่าคงที่ประเภทข้อความ CodeSite ใหม่สำหรับตัวจัดรูปแบบแต่ละตัว ด้านบนนี้เราได้กำหนดค่าคงที่ไว้สองตัวแล้ว โปรดทราบว่าค่าคงที่ควรมากกว่า csmUser แต่ต้องไม่เกิน 32,000 พิมพ์ TCSEmployee = บันทึก นามสกุล: สตริง; เงินเดือน: สกุลเงิน; Boolean; end; บันทึกด้านบนเป็นประเภทข้อมูลที่กำหนดเองที่เราต้องการส่ง TCSEmployeeSummaryFormatter = คลาส (TCSFormatter) ฟังก์ชัน TypeName: แทนที่; ด้านบนคือคำจำกัดความของคลาสตัวจัดรูปแบบที่กำหนดเองสองคลาส ตัวจัดรูปแบบตัวแรกจะจัดรูปแบบบันทึก TCSEmployee เป็นรูปแบบข้อความ และผู้จัดรูปแบบที่สองจะจัดรูปแบบบันทึก TCSEmployee เป็นรูปแบบตาราง การใช้งานใช้ SysUtils; {========================================} {= = วิธี TCSEmployeeSummaryFormatter ==} {=========================================} ฟังก์ชัน TCSEmployeeSummaryFormatter .InspectorType: TCSInspectorType; start Result := itStockStringList end; ขั้นตอนแรกในการใช้ฟอร์แมตเตอร์แบบกำหนดเองคือการกำหนดประเภทของวิวเวอร์ในตัวที่จะใช้เพื่อดูข้อมูลที่จัดรูปแบบ ในกรณีนี้ จะใช้วิวเวอร์รายการสตริง ประเภทตัวแสดงจะถูกใช้โดยเมธอด FormatData ขั้นตอน TCSEmployeeSummaryFormatData( var Data ); var EmpRec: TCSEmployee; start EmpRec.Address ( Data ); AddLine ( EmpRec.City + ) ', ' + EmpRec.State + ' ' + EmpRec.ZipCode ); AddLine( '' ); AddLine( 'โทรศัพท์: ' + EmpRec.PhoneNumber ); AddLine( 'วันที่จ้างงาน: ' + DateToStr( EmpRec.HireDate ) ); m', [ EmpRec.Salary ] ) ); AddLine( '' ); AddLine( 'วันหยุด: ' + IntToStr( EmpRec.VacationDays ) ); AddLine( 'Sick Days: ' + IntToStr( EmpRec.SickDays ) ); ถ้า EmpRec.Manager แล้ว AddLine( 'ผู้จัดการ: ใช่' ) มิฉะนั้น AddLine( 'ผู้จัดการ: ไม่' ); ; เมธอด FormatData เป็นส่วนหลัก โปรดทราบว่าพารามิเตอร์ Data ที่ส่งผ่านไปยังเมธอด FormatData เป็นพารามิเตอร์ตัวแปรที่ไม่ได้พิมพ์ ซึ่งหมายความว่าพารามิเตอร์นี้สามารถเป็นประเภทข้อมูลใดก็ได้ โดยผ่านขั้นตอนการลงทะเบียนรูปแบบ เราสามารถมั่นใจได้ว่าประเภทที่บังคับจะถูกแมปกับบันทึกข้อมูลที่กำหนดเองโดยไม่มีข้อผิดพลาดในการแปลง หลังจากแปลงชนิดข้อมูลแล้ว เราสามารถจัดรูปแบบข้อมูลได้ ที่นี่เราใช้วิธี AddLine ของคลาสพื้นฐาน TCSFormatter เพื่อเพิ่มเส้นแบ่งระหว่างสตริงสำหรับการจัดรูปแบบ ฟังก์ชัน TCSEmployeeSummaryFormatter.TypeName: string; beginning Result := 'TCSEmployee'; end; การโอเวอร์โหลดของเมธอด TypeName เป็นทางเลือก แต่โดยปกติแล้วเราสามารถใช้เพื่อส่งคืนสตริงที่ปรากฏในรายการข้อความ {=========================================} {== วิธีการ TCSEmployeeDetailsFormatter == } {=========================================} ฟังก์ชัน TCSEmployeeDetailsFormatter.InspectorType: TCSInspectorType ; เริ่มผลลัพธ์ := itStockGrid สิ้นสุด; สำหรับตัวจัดรูปแบบรายละเอียดพนักงาน โปรแกรมดูตารางที่มีชื่อจะถูกใช้เพื่อดูข้อมูล: ขั้นตอน TCSEmployeeDetailsFormatter.FormatData( var Data ); var EmpRec: TCSEmployee; beginning EmpRec := TCSEmployee( Data ); ; AddNameValuePair( 'FirstName', EmpRec.FirstName ); AddNameValuePair( 'ที่อยู่', EmpRec.State ); AddNameValuePair( 'เมือง', EmpRec.City ); AddNameValuePair( 'PhoneNumber', EmpRec.PhoneNumber ); AddNameValuePair( 'HireDate', EmpRec.HireDate ); AddNameValuePair( 'เงินเดือน', รูปแบบ( '%m', [ EmpRec.Salary ] ) ); AddNameValuePair( 'VacationDays', EmpRec.VacationDays ); ); AddNameValuePair( 'ผู้จัดการ', EmpRec.Manager ); สิ้นสุดที่นี่เพื่อจัดรูปแบบข้อมูลในโปรแกรมดูตาราง เราใช้วิธี AddNameValuePair ฟังก์ชัน TCSEmployeeDetailsFormatter.TypeName: string; beginning Result := 'TCSEmployee'; end; =============} {== วิธีการสนับสนุน ==} {======================} ขั้นตอน CSSendEmployeeSummary ( const ข่าวสารเกี่ยวกับ: สตริง; EmpRec: TCSEmployee ); เริ่มต้น CodeSite.SendCustomData ( csmEmployeeSummary , Msg , EmpRec ); end; สุดท้ายนี้ อย่าลืมเรียกเมธอด CSObjectManager.RegisterCustomFormatter เพื่อลงทะเบียนฟอร์แมตเตอร์กับ CodeSite Object Manager การเริ่มต้น CSObjectManager.RegisterCustomFormatter ( csmEmployeeSummary, TCSEmployeeSummaryFormatter ); CSObjectManager.RegisterCustomFormatter ( csmEmployeeDetails, TCSEmployeeDetailsFormatter );