มีการจัดการฐานรหัสที่ไม่ใช่ OO ขนาดใหญ่เท่าใด


27

ฉันมักจะเห็นสิ่งที่เป็นนามธรรมเป็นคุณสมบัติที่มีประโยชน์มากที่ OO มีให้สำหรับการจัดการโค้ด แต่จะมีการจัดการฐานรหัสที่ไม่ใช่ OO ขนาดใหญ่ได้อย่างไร หรือว่ากลายเป็น " Big Ball of Mud " ในที่สุด?

อัปเดต:
ดูเหมือนว่าทุกคนกำลังคิดว่า 'นามธรรม' เป็นเพียงการทำให้เป็นโมดูลหรือการซ่อนข้อมูล แต่ IMHO ก็หมายถึงการใช้ 'Abstract Classes' หรือ 'Interfaces' ซึ่งเป็นสิ่งจำเป็นสำหรับการพึ่งพาการฉีดและการทดสอบ รหัสฐานที่ไม่ใช่ OO จะจัดการสิ่งนี้ได้อย่างไร นอกจากนี้ยังมีสิ่งที่เป็นนามธรรมนอกจากนี้การห่อหุ้มยังช่วยในการจัดการฐานรหัสขนาดใหญ่ในขณะที่มันกำหนดและ จำกัด ความสัมพันธ์ระหว่างข้อมูลและฟังก์ชั่น

ด้วย C มันเป็นไปได้มากที่จะเขียนโค้ดหลอก -OO ฉันไม่รู้เกี่ยวกับภาษาที่ไม่ใช่ OO มากนัก เป็นวิธีจัดการฐานรหัส C ขนาดใหญ่หรือไม่


6
โปรดอธิบายวัตถุด้วยวิธีที่ไม่เชื่อเรื่องภาษา มันคืออะไรมันถูกดัดแปลงอย่างไรมันควรสืบทอดอะไรและมันควรมีอะไรบ้าง? เคอร์เนล Linux เต็มไปด้วยโครงสร้างที่จัดสรรซึ่งมีตัวช่วยและตัวชี้ฟังก์ชันจำนวนมาก แต่นั่นอาจจะไม่เป็นไปตามคำนิยามของวัตถุที่มุ่งเน้นมากที่สุด แต่มันเป็นหนึ่งในตัวอย่างที่ดีที่สุดของฐานรหัสที่ได้รับการดูแลเป็นอย่างดี ทำไม? เพราะผู้ดูแลระบบย่อยทุกคนรู้ว่าอะไรอยู่ในความรับผิดชอบของพวกเขา
ทิมโพสต์

ในวิธีที่ไม่เชื่อเรื่องภาษาโปรดอธิบายว่าคุณเห็นการจัดการฐานรหัสได้อย่างไรและ OO เกี่ยวข้องกับเรื่องนี้อย่างไร
David Thornley

@Tim Post ฉันสนใจเกี่ยวกับการจัดการรหัสเคอร์เนล Linux คุณช่วยอธิบายระบบเพิ่มเติมได้ไหม? อาจเป็นคำตอบด้วยตัวอย่าง?
Gulshan

7
ในสมัยก่อนเราใช้การเชื่อมโยงแยกต่างหากสำหรับ mocks และ stubs สำหรับการทดสอบหน่วย การพึ่งพาการฉีดเป็นเพียงหนึ่งเทคนิคในหลาย ๆ การรวบรวมแบบมีเงื่อนไขเป็นอีกเรื่องหนึ่ง
Macneil

ฉันคิดว่ามันเป็นเรื่องที่ยืดยาวในการอ้างถึงฐานรหัสขนาดใหญ่ (OO หรืออย่างอื่น) เป็น "จัดการ" มันจะเป็นการดีถ้าคุณมีคำจำกัดความที่ดีกว่าของคำกลางในคำถามของคุณ
tottinge

คำตอบ:


43

ดูเหมือนว่าคุณจะคิดว่า OOP เป็นหนทางเดียวในการบรรลุเป้าหมายที่เป็นนามธรรม

ในขณะที่ OOP นั้นดีมากในการทำเช่นนั้น แต่ก็ไม่ได้เป็นวิธีเดียวเท่านั้น โครงการขนาดใหญ่สามารถถูกจัดการได้โดยการทำให้เป็นโมดูลแบบแยกส่วน (ดูที่ Perl หรือ Python ซึ่งทั้งสองอย่างนั้นเก่งและใช้ภาษาทำงานเช่น ML และ Haskell) และใช้กลไกต่าง ๆ เช่นเทมเพลต (ใน C ++)


27
+1 นอกจากนี้คุณยังสามารถเขียน "Big Ball of Mud" โดยใช้ OOP หากคุณไม่รู้ว่าคุณกำลังทำอะไรอยู่
Larry Coleman

รหัสฐาน C คืออะไร?
Gulshan

6
@Gulshan: ฐานรหัส C ขนาดใหญ่จำนวนมากคือ OOP เพียงเพราะ C ไม่มีคลาสไม่ได้หมายความว่า OOP ไม่สามารถทำได้ด้วยความพยายาม นอกจากนี้ C ยังช่วยให้การทำให้เป็นโมดูลที่ดีโดยใช้ส่วนหัวและสำนวน PIMPL ไม่สะดวกสบายหรือทรงพลังเท่าโมดูลในภาษาสมัยใหม่ แต่ก็ดีพออีกครั้ง
Konrad Rudolph

9
C อนุญาตการทำให้เป็นโมดูลในระดับไฟล์ ส่วนต่อประสานจะอยู่ในไฟล์. h ฟังก์ชั่นที่เปิดเผยต่อสาธารณะในไฟล์. c และตัวแปรส่วนตัวและฟังก์ชั่นจะได้รับstaticตัวดัดแปลงการเข้าถึงที่แนบมา
David Thornley

1
@ Konrad: ในขณะที่ฉันยอมรับว่า OOP ไม่ใช่วิธีเดียวที่จะทำฉันเชื่อว่า OP น่าจะมี C อยู่ในใจอย่างเคร่งครัดซึ่งไม่ใช่การทำงานหรือภาษาแบบไดนามิก ดังนั้นฉันสงสัยว่าการกล่าวถึง Perl และ Haskell จะเป็นประโยชน์กับเขา / เธอ ฉันค้นหาความคิดเห็นของคุณมีความเกี่ยวข้องและเป็นประโยชน์ต่อ OP ( ไม่ได้หมายความว่า OOP จะไม่สามารถทำได้ด้วยความพยายามสักเล็กน้อย ); คุณอาจลองเพิ่มเป็นคำตอบแยกต่างหากพร้อมรายละเอียดเพิ่มเติมอาจสนับสนุนด้วยข้อมูลโค้ดหรือลิงค์สองสามตัว อย่างน้อยมันก็จะชนะการโหวตของฉันและอาจเป็นไปได้ว่า OP :)
Groo

11

โมดูลฟังก์ชัน (ภายนอก / ภายใน) รูทีนย่อย ...

ดังที่ Konrad กล่าวว่า OOP ไม่ใช่วิธีเดียวในการจัดการฐานรหัสขนาดใหญ่ ตามความเป็นจริงแล้วมีการเขียนซอฟต์แวร์ค่อนข้างมากก่อนหน้านี้ (ก่อนหน้า C ++ *)


* และใช่ฉันรู้ว่า C ++ ไม่ใช่เพียงหนึ่งเดียวที่สนับสนุน OOP แต่อย่างใดเมื่อวิธีนั้นเริ่มที่จะใช้ความเฉื่อย
โกง


6

การเปลี่ยนแปลงที่เกิดขึ้นไม่บ่อยนัก (คิดว่าการคำนวนการประกันสังคมเกษียณอายุ) และ / หรือความรู้ที่ฝังลึกอยู่เพราะคนที่ดูแลระบบเช่นนี้กำลังทำอยู่ชั่วขณะ (ความเห็นถากถางดูถูกเหยียดหยามคืองานรักษาความปลอดภัย)

โซลูชันที่ดีกว่าคือการตรวจสอบความถูกต้องซ้ำซึ่งฉันหมายถึงการทดสอบอัตโนมัติ (เช่นการทดสอบหน่วย) และการทดสอบโดยมนุษย์ซึ่งทำตามขั้นตอนที่ถูกสั่งซื้อ (เช่นการทดสอบการถดถอย) "แทนที่จะตรงข้ามกับการคลิก

ในการเริ่มเคลื่อนไปสู่การทดสอบอัตโนมัติด้วย codebase ที่มีอยู่ฉันแนะนำให้อ่านMichael Feather's การทำงานอย่างมีประสิทธิภาพด้วย Legacy Codeซึ่งมีรายละเอียดแนวทางสำหรับการนำ codebase ที่มีอยู่มาจนกระทั่งกรอบการทดสอบ OO ที่ทำซ้ำได้หรือไม่ สิ่งนี้นำไปสู่การเรียงลำดับของความคิดที่คนอื่นตอบด้วยเช่นการทำให้เป็นโมดูล แต่หนังสืออธิบายวิธีการที่ถูกต้องในการทำเช่นนั้นโดยไม่ทำลายสิ่งต่างๆ


+1 สำหรับหนังสือ Michael Feather`s เมื่อคุณรู้สึกมีความสุขเกี่ยวกับขนาดใหญ่น่าเกลียดรหัสฐาน (อีกครั้ง) -read มัน :)
Matthieu

5

แม้ว่าการฉีดการพึ่งพาตามอินเตอร์เฟสหรือคลาสนามธรรมเป็นวิธีที่ดีมากในการทำการทดสอบ แต่ก็ไม่จำเป็น อย่าลืมว่าเกือบทุกภาษามีทั้งตัวชี้ฟังก์ชั่นหรือตัวทดสอบซึ่งสามารถทำอะไรก็ได้ที่คุณสามารถทำได้ด้วยอินเทอร์เฟซหรือคลาสนามธรรม (ปัญหาคือพวกเขาสามารถทำอะไรได้มากกว่ารวมถึงสิ่งเลวร้ายมากมาย ในตัวเองให้ข้อมูลเมตา) โปรแกรมดังกล่าวสามารถบรรลุการฉีดพึ่งพากับกลไกเหล่านี้

ฉันพบว่าการเข้มงวดกับข้อมูลเมตาจะเป็นประโยชน์อย่างมาก ในภาษา OO ความสัมพันธ์ระหว่างบิตของโค้ดถูกกำหนด (เป็นระดับ) โดยโครงสร้างคลาสในลักษณะที่เป็นมาตรฐานเพียงพอที่จะมีสิ่งต่าง ๆ เช่น API การสะท้อนกลับ ในขั้นตอนภาษามันจะมีประโยชน์ในการประดิษฐ์ตัวเอง

ฉันยังพบว่าการสร้างรหัสมีประโยชน์มากขึ้นในภาษาขั้นตอน (เปรียบเทียบกับภาษาเชิงวัตถุ) สิ่งนี้รับประกันว่า meta-data จะซิงค์กับรหัส (เนื่องจากมันถูกใช้เพื่อสร้างมัน) และทำให้คุณมีบางอย่างเช่นจุดตัดของการเขียนโปรแกรมที่มุ่งเน้นในเชิงกว้าง - สถานที่ที่คุณสามารถฉีดรหัสเมื่อคุณต้องการ บางครั้งมันเป็นวิธีเดียวที่จะเขียนโปรแกรม DRY ในสภาพแวดล้อมที่ฉันสามารถหาคำตอบได้


3

ที่จริงแล้วเมื่อคุณเพิ่งค้นพบฟังก์ชั่นการสั่งซื้อครั้งแรกนั้นเป็นสิ่งที่คุณต้องการสำหรับการผกผันของการพึ่งพา

C รองรับฟังก์ชั่นการสั่งซื้อครั้งแรกและแม้กระทั่งการปิดในระดับหนึ่ง และมาโคร C เป็นคุณสมบัติที่ทรงพลังสำหรับการเขียนโปรแกรมทั่วไปหากจัดการด้วยความระมัดระวัง

มันคือทั้งหมดที่มี SGLIBเป็นตัวอย่างที่ดีเกี่ยวกับวิธีการที่ C สามารถใช้ในการเขียนโค้ดที่สามารถใช้ซ้ำได้สูง และฉันเชื่อว่ายังมีอีกมาก


2

แม้จะไม่มีสิ่งที่เป็นนามธรรมโปรแกรมส่วนใหญ่ก็แยกออกเป็นส่วน ๆ ส่วนเหล่านั้นมักเกี่ยวข้องกับงานหรือกิจกรรมที่เฉพาะเจาะจงและคุณทำงานในลักษณะเดียวกับที่คุณทำงานกับบิตที่เจาะจงที่สุดของโปรแกรมที่เป็นนามธรรม

ในโครงการขนาดเล็กถึงขนาดกลางนี่เป็นเรื่องง่ายที่จะทำเช่นนั้นด้วยการใช้ OO ที่พิถีพิถัน


2

นามธรรม, คลาสนามธรรม, การฉีดพึ่งพา, encapsulation, อินเตอร์เฟสและอื่น ๆ ไม่ใช่วิธีเดียวในการควบคุมฐานรหัสขนาดใหญ่ นี่เป็นเพียงวิธีการเชิงวัตถุ

ความลับหลักคือการหลีกเลี่ยงที่จะคิดว่า OOP เมื่อโค้ดที่ไม่ใช่ OOP

Modularity เป็นกุญแจสำคัญในภาษาที่ไม่ใช่ OO ใน C สามารถทำได้เช่นเดียวกับ David Thornley ที่กล่าวถึงในความคิดเห็น:

ส่วนต่อประสานจะอยู่ในไฟล์. h ฟังก์ชั่นที่เปิดเผยต่อสาธารณะในไฟล์. c และตัวแปรส่วนตัวและฟังก์ชั่นจะได้รับตัวดัดแปลงการเข้าถึงแบบสแตติก


1

วิธีหนึ่งในการจัดการรหัสคือการแยกรหัสออกเป็นรหัสประเภทต่อไปนี้ตามบรรทัดของสถาปัตยกรรม MVC (model-view-controller)

  • Input handler - รหัสนี้เกี่ยวกับอุปกรณ์ป้อนข้อมูลเช่นเมาส์แป้นพิมพ์พอร์ตเครือข่ายหรือ abstractions ระดับที่สูงขึ้นเช่นเหตุการณ์ของระบบ
  • ตัวจัดการเอาต์พุต - รหัสนี้เกี่ยวข้องกับการใช้ข้อมูลเพื่อจัดการอุปกรณ์ภายนอกเช่นจอภาพไฟพอร์ตเครือข่าย ฯลฯ
  • รุ่น - รหัสนี้เกี่ยวข้องกับการประกาศโครงสร้างของข้อมูลถาวรของคุณกฎสำหรับการตรวจสอบข้อมูลถาวรและบันทึกข้อมูลถาวรไปยังดิสก์ (หรืออุปกรณ์ข้อมูลถาวรอื่น ๆ )
  • Views - รหัสนี้เกี่ยวข้องกับการจัดรูปแบบข้อมูลเพื่อตอบสนองความต้องการของวิธีการรับชมที่หลากหลายเช่นเว็บเบราว์เซอร์ (HTML / CSS), GUI, บรรทัดคำสั่ง, รูปแบบข้อมูลโปรโตคอลการสื่อสาร (เช่น JSON, XML, ASN.1 เป็นต้น)
  • อัลกอริธึม - รหัสนี้จะแปลงชุดข้อมูลอินพุตซ้ำเป็นชุดข้อมูลเอาต์พุตโดยเร็วที่สุด
  • ตัวควบคุม - รหัสนี้ใช้อินพุตผ่านตัวจัดการอินพุตแยกวิเคราะห์อินพุตโดยใช้อัลกอริธึมจากนั้นแปลงข้อมูลด้วยอัลกอริธึมอื่น ๆ โดยเลือกที่จะรวมอินพุตกับข้อมูลถาวรหรือเพียงแปลงอินพุตจากนั้นเลือกบันทึกข้อมูลที่แปลงแล้ว ซอฟต์แวร์และเลือกแปลงข้อมูลผ่านซอฟต์แวร์มุมมองเพื่อแสดงผลไปยังอุปกรณ์ส่งออก

วิธีการของการจัดระเบียบรหัสนี้ทำงานได้ดีสำหรับซอฟต์แวร์ที่เขียนในภาษา OO หรือภาษาที่ไม่ใช่ OO ใด ๆ เนื่องจากรูปแบบการออกแบบทั่วไปมักจะใช้ร่วมกันในแต่ละพื้นที่ นอกจากนี้ขอบเขตของโค้ดเหล่านี้มักจะถูกรวมเข้าด้วยกันอย่างอิสระมากที่สุดยกเว้นอัลกอริธึมเพราะพวกมันเชื่อมโยงรูปแบบข้อมูลจากอินพุตไปยังโมเดลและจากนั้นไปยังเอาต์พุต

การวิวัฒนาการของระบบมักจะอยู่ในรูปแบบของการที่ซอฟต์แวร์ของคุณจัดการกับอินพุตได้มากขึ้นหรือมีเอาต์พุตมากกว่า แต่โมเดลและมุมมองจะเหมือนกันและตัวควบคุมจะทำงานคล้ายกันมาก หรือระบบอาจต้องใช้เวลาในการสนับสนุนเอาต์พุตที่หลากหลายมากขึ้นแม้ว่าอินพุต, โมเดล, อัลกอริทึมจะเหมือนกันและคอนโทรลเลอร์และมุมมองจะคล้ายกัน หรืออาจเพิ่มระบบเพื่อเพิ่มโมเดลและอัลกอริธึมใหม่สำหรับชุดอินพุตเดียวกันเอาต์พุตที่คล้ายกันและมุมมองที่คล้ายกัน

วิธีหนึ่งในการเขียนโปรแกรม OO ทำให้การจัดระเบียบรหัสยากเพราะบางคลาสนั้นเชื่อมโยงกับโครงสร้างข้อมูลถาวรและบางตัวไม่ หากโครงสร้างข้อมูลถาวรมีความสัมพันธ์อย่างใกล้ชิดกับสิ่งต่าง ๆ เช่นการเรียงซ้อน 1: N ความสัมพันธ์หรือความสัมพันธ์ m: n มันเป็นเรื่องยากมากที่จะตัดสินใจขอบเขตของชั้นเรียนจนกว่าคุณจะได้เข้ารหัสส่วนที่สำคัญและมีความหมายของระบบของคุณก่อนที่คุณจะรู้ว่า . คลาสใด ๆ ที่เชื่อมโยงกับโครงสร้างข้อมูลถาวรจะยากต่อการพัฒนาเมื่อสคีมาของการเปลี่ยนแปลงข้อมูลถาวร คลาสที่จัดการกับอัลกอริทึมการจัดรูปแบบและการแยกวิเคราะห์มีโอกาสน้อยที่จะมีความเสี่ยงต่อการเปลี่ยนแปลงในสคีมาของโครงสร้างข้อมูลถาวร การใช้การจัดประเภทรหัส MVC จะแยกการเปลี่ยนแปลงรหัสที่ยุ่งที่สุดออกเป็นรหัสรุ่นได้ดียิ่งขึ้น


0

เมื่อทำงานในภาษาที่ไม่มีโครงสร้างแบบ inbuilt และคุณสมบัติขององค์กร (เช่นถ้าไม่มีเนมสเปซ, แพ็คเกจ, ชุดประกอบ ฯลฯ ... ) หรือสิ่งเหล่านี้ไม่เพียงพอที่จะทำให้ codebase ของขนาดนั้นอยู่ภายใต้การควบคุมการตอบสนองตามธรรมชาติคือการพัฒนา กลยุทธ์ของเราในการจัดระเบียบรหัส

กลยุทธ์องค์กรนี้อาจรวมถึงมาตรฐานที่เกี่ยวข้องกับการจัดเก็บไฟล์ต่าง ๆ สิ่งที่ต้องเกิดขึ้นก่อน / หลังการดำเนินงานบางประเภทและการตั้งชื่ออนุสัญญาและมาตรฐานการเข้ารหัสอื่น ๆ รวมถึง "นี่คือวิธีการตั้งค่า - อย่าไปยุ่งกับมัน! " พิมพ์ความคิดเห็น - ซึ่งใช้ได้ตราบเท่าที่พวกเขาอธิบายว่าทำไม

เนื่องจากกลยุทธ์มีแนวโน้มที่จะได้รับการปรับแต่งให้เหมาะกับความต้องการเฉพาะของโครงการ (ผู้คนเทคโนโลยีสิ่งแวดล้อม ฯลฯ ... ) มันยากที่จะให้โซลูชั่นที่มีขนาดพอดีกับการจัดการฐานรหัสขนาดใหญ่

ดังนั้นฉันเชื่อว่าคำแนะนำที่ดีที่สุดคือการยอมรับกลยุทธ์เฉพาะโครงการและทำให้การจัดการเป็นสิ่งสำคัญลำดับแรก: จัดทำเอกสารโครงสร้างสาเหตุที่เป็นเช่นนั้นกระบวนการในการเปลี่ยนแปลงตรวจสอบเพื่อให้แน่ใจว่าปฏิบัติตาม และตรึง: เปลี่ยนเมื่อจำเป็นต้องเปลี่ยน

เราส่วนใหญ่คุ้นเคยกับคลาสและวิธีการ refactoring แต่ด้วย codebase ขนาดใหญ่ในภาษาดังกล่าวมันเป็นกลยุทธ์การจัดระเบียบตัวเอง (พร้อมเอกสารประกอบ) ที่จะต้องมีการ refactored ตามและเมื่อจำเป็น

เหตุผลนั้นเหมือนกับ refactoring: คุณจะพัฒนาบล็อกทางจิตต่อการทำงานในส่วนเล็ก ๆ ของระบบถ้าคุณรู้สึกว่าองค์กรโดยรวมของมันยุ่งเหยิงและในที่สุดก็จะทำให้มันแย่ลง มัน).

ข้อแม้นั้นเหมือนกัน: ใช้การทดสอบการถดถอยตรวจสอบให้แน่ใจว่าคุณสามารถย้อนกลับได้อย่างง่ายดายหากการปรับโครงสร้างเกิดความผิดพลาดและการออกแบบเพื่อให้การรีแฟคเตอร์เป็นครั้งแรก (หรือคุณจะไม่ทำมัน!)

ฉันเห็นด้วยว่ามันยากกว่าการ refactoring direct code และมันยากที่จะตรวจสอบ / ปกปิดเวลาจากผู้จัดการ / ลูกค้าที่อาจไม่เข้าใจว่าทำไมมันถึงต้องทำ แต่สิ่งเหล่านี้เป็นโครงการประเภทที่เสี่ยงต่อการเน่าซอฟต์แวร์ เกิดจากการออกแบบระดับบนที่ไม่ยืดหยุ่น ...


0

หากคุณถามเกี่ยวกับการจัดการ code-base ขนาดใหญ่คุณจะถามถึงวิธีการทำให้ code base ของคุณมีโครงสร้างที่ดีในระดับที่ค่อนข้างหยาบ (ไลบรารี / โมดูล / การสร้างระบบย่อย / ใช้ namespaces / มีเอกสารที่ถูกต้องในสถานที่ที่เหมาะสม ฯลฯ ) หลักการ OO โดยเฉพาะอย่างยิ่ง 'คลาสที่เป็นนามธรรม' หรือ 'อินเทอร์เฟซ' เป็นหลักการในการทำให้โค้ดของคุณสะอาดอยู่ในระดับที่มีรายละเอียดมาก ดังนั้นเทคนิคในการรักษาฐานรหัสขนาดใหญ่ที่จัดการได้ไม่แตกต่างกันสำหรับ OO หรือไม่ใช่ OO-code


0

วิธีจัดการของมันคือคุณค้นหาขอบเขตขององค์ประกอบที่คุณใช้ ตัวอย่างเช่นองค์ประกอบต่อไปนี้ใน C ++ มีเส้นขอบที่ชัดเจนและการพึ่งพาใด ๆ ที่อยู่นอกเส้นขอบต้องพิจารณาอย่างรอบคอบ:

  1. ฟังก์ชั่นฟรี
  2. ฟังก์ชั่นสมาชิก
  3. ชั้น
  4. วัตถุ
  5. อินเตอร์เฟซ
  6. การแสดงออก
  7. คอนสตรัคโทร / การสร้างวัตถุ
  8. ฟังก์ชั่นการโทร
  9. ประเภทพารามิเตอร์เทมเพลต

เมื่อรวมองค์ประกอบเหล่านี้เข้ากับการจดจำขอบเขตคุณสามารถสร้างรูปแบบการเขียนโปรแกรมเกือบทุกรูปแบบที่คุณต้องการภายใน c ++

ตัวอย่างของฟังก์ชั่นนี้สำหรับฟังก์ชั่นที่จะจำได้ว่ามันไม่ดีที่จะเรียกฟังก์ชั่นอื่น ๆ จากฟังก์ชั่นเพราะมันทำให้เกิดการพึ่งพาคุณควรจะเรียกฟังก์ชั่นสมาชิกของพารามิเตอร์ของฟังก์ชั่นเดิม


-1

ความท้าทายทางเทคนิคที่ใหญ่ที่สุดคือปัญหาเนมสเปซ การเชื่อมโยงบางส่วนสามารถใช้แก้ปัญหานี้ได้ วิธีที่ดีกว่าคือการออกแบบโดยใช้มาตรฐานการเข้ารหัส มิฉะนั้นสัญลักษณ์ทั้งหมดจะกลายเป็นความยุ่งเหยิง


-2

Emacs เป็นตัวอย่างที่ดีของสิ่งนี้:

สถาปัตยกรรม Emacs

ส่วนประกอบของ Emacs

การทดสอบ Emacs Lisp ใช้skip-unlessและlet-bindทำการตรวจจับและทดสอบคุณสมบัติ:

บางครั้งมันไม่สมเหตุสมผลเลยที่จะทำการทดสอบเนื่องจากไม่มีเงื่อนไขเบื้องต้น คุณสมบัติ Emacs ที่ต้องการอาจไม่ได้รวบรวมไว้ฟังก์ชันที่จะทดสอบสามารถเรียกเลขฐานสองภายนอกซึ่งอาจไม่สามารถใช้กับเครื่องทดสอบได้ ในกรณีนี้skip-unlessสามารถใช้แมโครเพื่อข้ามการทดสอบ:

 (ert-deftest test-dbus ()
   "A test that checks D-BUS functionality."
   (skip-unless (featurep 'dbusbind))
   ...)

ผลลัพธ์ของการรันการทดสอบไม่ควรขึ้นอยู่กับสถานะปัจจุบันของสภาพแวดล้อมและการทดสอบแต่ละครั้งควรปล่อยให้สภาพแวดล้อมอยู่ในสภาพเดียวกันกับที่พบโดยเฉพาะอย่างยิ่งการทดสอบไม่ควรขึ้นอยู่กับตัวแปรหรือตะขอของ Emacs เองและ หากต้องทำการเปลี่ยนแปลงใด ๆ กับสถานะของ Emacs หรือสถานะภายนอกของ Emacs (เช่นระบบไฟล์) ควรยกเลิกการเปลี่ยนแปลงเหล่านี้ก่อนที่จะส่งคืนโดยไม่คำนึงว่าจะผ่านหรือล้มเหลว

การทดสอบไม่ควรขึ้นอยู่กับสภาพแวดล้อมเพราะการพึ่งพาดังกล่าวสามารถทำให้การทดสอบเปราะหรือนำไปสู่ความล้มเหลวที่เกิดขึ้นภายใต้สถานการณ์บางอย่างเท่านั้นและยากที่จะทำซ้ำ แน่นอนรหัสภายใต้การทดสอบอาจมีการตั้งค่าที่มีผลต่อพฤติกรรมของมัน ในกรณีนั้นเป็นการดีที่สุดที่จะทำการทดสอบlet-bindตัวแปรการตั้งค่าทั้งหมดเพื่อตั้งค่าการกำหนดค่าเฉพาะสำหรับช่วงเวลาของการทดสอบ การทดสอบยังสามารถตั้งค่าการกำหนดค่าที่แตกต่างกันจำนวนหนึ่งและเรียกใช้รหัสภายใต้การทดสอบกับแต่ละ

เช่นเดียวกับ SQLite นี่คือการออกแบบ:

  1. sqlite3_open () →เปิดการเชื่อมต่อกับฐานข้อมูล SQLite ใหม่หรือที่มีอยู่ คอนสตรัคสำหรับ sqlite3

  2. sqlite3 →วัตถุเชื่อมต่อฐานข้อมูล สร้างโดย sqlite3_open () และถูกทำลายโดย sqlite3_close ()

  3. sqlite3_stmt →วัตถุคำสั่งที่เตรียมไว้ สร้างโดย sqlite3_prepare () และถูกทำลายโดย sqlite3_finalize ()

  4. sqlite3_prepare () →รวบรวมข้อความ SQL เป็นรหัสไบต์ที่จะทำงานของการสืบค้นหรือปรับปรุงฐานข้อมูล คอนสตรัคสำหรับ sqlite3_stmt

  5. sqlite3_bind () →จัดเก็บข้อมูลแอปพลิเคชันลงในพารามิเตอร์ของ SQL ดั้งเดิม

  6. sqlite3_step () →เลื่อน sqlite3_stmt ไปยังแถวผลลัพธ์ถัดไปหรือจนจบ

  7. sqlite3_column () →ค่าคอลัมน์ในแถวผลลัพธ์ปัจจุบันสำหรับ sqlite3_stmt

  8. sqlite3_finalize () → Destructor สำหรับ sqlite3_stmt

  9. sqlite3_exec () →ฟังก์ชั่น wrapper ที่ทำ sqlite3_prepare (), sqlite3_step (), sqlite3_column (), และ sqlite3_finalize () สำหรับสตริงของคำสั่ง SQL ตั้งแต่หนึ่งประโยคขึ้นไป

  10. sqlite3_close () → Destructor สำหรับ sqlite3

สถาปัตยกรรม sqlite3

คอมโพเนนต์ Tokenizer, Parser และ Code Generator ใช้ในการประมวลผลคำสั่ง SQL และแปลงเป็นโปรแกรมที่ปฏิบัติการได้ในภาษาเครื่องเสมือนหรือรหัสไบต์ พูดประมาณชั้นนำเหล่านี้สามชั้นใช้sqlite3_prepare_v2 () โค้ดไบต์ที่สร้างโดยสามเลเยอร์แรกเป็นคำสั่งที่เตรียมไว้. โมดูลเครื่องเสมือนมีหน้าที่ในการเรียกใช้รหัสไบต์คำสั่ง SQL โมดูล B-Tree จัดระเบียบไฟล์ฐานข้อมูลลงในร้านค้าคีย์ / ค่าหลายแห่งพร้อมกับคีย์ที่สั่งซื้อและประสิทธิภาพลอการิทึม โมดูลเพจเจอร์มีหน้าที่ในการโหลดหน้าของไฟล์ฐานข้อมูลลงในหน่วยความจำสำหรับการใช้งานและการควบคุมการทำธุรกรรมและสำหรับการสร้างและบำรุงรักษาไฟล์เจอร์นัลที่ป้องกันความเสียหายของฐานข้อมูลหลังจากเกิดความผิดพลาดหรือไฟดับ อินเทอร์เฟซระบบปฏิบัติการเป็นนามธรรมที่ให้ชุดของรูทีนทั่วไปสำหรับการปรับ SQLite ให้ทำงานบนระบบปฏิบัติการที่แตกต่างกัน พูดประมาณด้านล่างสี่ชั้นใช้sqlite3_step ()

ตารางเสมือน sqlite3

ตารางเสมือนเป็นวัตถุที่ลงทะเบียนกับการเชื่อมต่อฐานข้อมูล SQLite แบบเปิด จากมุมมองของคำสั่ง SQL วัตถุตารางเสมือนจะดูเหมือนกับตารางหรือมุมมองอื่น ๆ แต่เบื้องหลังการสืบค้นและการปรับปรุงในตารางเสมือนจะเรียกวิธีการโทรกลับของวัตถุตารางเสมือนแทนการอ่านและการเขียนบนไฟล์ฐานข้อมูล

ตารางเสมือนอาจแสดงโครงสร้างข้อมูลในหน่วยความจำ หรืออาจแสดงมุมมองข้อมูลบนดิสก์ที่ไม่ได้อยู่ในรูปแบบ SQLite หรือแอปพลิเคชันอาจคำนวณเนื้อหาของตารางเสมือนตามต้องการ

นี่คือการใช้งานที่มีอยู่และได้รับการจดทะเบียนสำหรับตารางเสมือน:

อินเตอร์เฟซการค้นหาข้อความแบบเต็ม
ดัชนีเชิงพื้นที่โดยใช้ R-Trees
ใคร่ครวญเนื้อหาดิสก์ของไฟล์ฐานข้อมูล SQLite (ตารางเสมือน dbstat)
อ่านและ / หรือเขียนเนื้อหาของไฟล์ค่าที่คั่นด้วยเครื่องหมายจุลภาค (CSV)
เข้าถึงระบบไฟล์ของโฮสต์คอมพิวเตอร์ราวกับว่าเป็นตารางฐานข้อมูล
การเปิดใช้งานการจัดการข้อมูล SQL ในแพ็คเกจสถิติเช่น R

SQLite ใช้เทคนิคการทดสอบที่หลากหลายรวมถึง:

ชุดทดสอบที่พัฒนาขึ้นอย่างอิสระสามชุด
ครอบคลุมการทดสอบสาขา 100% ในการกำหนดค่าแบบไม่ใช้งาน
กรณีทดสอบหลายล้านรายการ
การทดสอบหน่วยความจำไม่เพียงพอ
การทดสอบข้อผิดพลาด I / O
การทดสอบการชนและการสูญเสียพลังงาน
การทดสอบฝอย
การทดสอบค่าขอบเขต
ปิดใช้งานการทดสอบการเพิ่มประสิทธิภาพ
การทดสอบการถดถอย
การทดสอบฐานข้อมูลผิดรูปแบบ
การใช้งาน assert () และการตรวจสอบเวลาทำงานอย่างกว้างขวาง
การวิเคราะห์ Valgrind
ตรวจสอบพฤติกรรมที่ไม่ได้กำหนด
รายการตรวจสอบ

อ้างอิง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.