อ่าน 3 นาที
การเขียนโปรแกรมแบบคัดลอกและวาง
การเขียนโปรแกรมแบบคัดลอกและวาง หรือบางครั้งเรียกว่า การวาง เฉยๆ นั้น คือการสร้าง โค้ด โปรแกรมคอมพิวเตอร์ ที่ซ้ำซากมาก โดยใช้ การคัดลอกและวาง โดย ส่วนใหญ่แล้วคำนี้มีความหมายเชิงลบ...
การเขียนโปรแกรมแบบคัดลอกและวาง

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

การนำโค้ดไลบรารีไปใช้
การคัดลอกและวางยังทำโดยโปรแกรมเมอร์ที่มีประสบการณ์ ซึ่งมักจะมีไลบรารีของโค้ดสำเร็จรูปและ อัลกอริธึมทั่วไปที่ผ่านการทดสอบมาอย่างดีและพร้อมใช้งานซึ่งสามารถปรับให้เข้ากับงานเฉพาะได้อย่างง่ายดาย[ 2 ]
การเขียนโปรแกรมแบบคัดลอกและวาง ซึ่ง ถือเป็นรูปแบบหนึ่งของการทำซ้ำโค้ดมีปัญหาโดยเนื้อแท้อยู่บ้าง ปัญหาเหล่านี้จะรุนแรงขึ้นหากโค้ดไม่ได้รักษาความเชื่อมโยงทางความหมายระหว่างข้อความต้นฉบับกับสำเนา ในกรณีนี้ หากจำเป็นต้องเปลี่ยนแปลง จะเสียเวลาไปกับการค้นหาตำแหน่งที่ซ้ำกันทั้งหมด (ปัญหานี้สามารถแก้ไขได้บางส่วนหากโค้ดต้นฉบับและ/หรือสำเนามีการใส่คำอธิบายอย่างเหมาะสม อย่างไรก็ตาม แม้จะทำเช่นนั้น ปัญหาก็ยังคงอยู่ คือการแก้ไขแบบเดียวกันหลายครั้ง นอกจากนี้ เนื่องจากการบำรุงรักษาโค้ดมักจะละเว้นการอัปเดตคำอธิบาย[ 3 ]คำอธิบายที่อธิบายตำแหน่งที่จะค้นหาโค้ดระยะไกลจึงมักจะล้าสมัย)
ผู้สนับสนุน วิธี การเชิงวัตถุยังคัดค้านการใช้ "ไลบรารีโค้ด" โดยการคัดลอกและวาง แทนที่จะสร้างสำเนาที่เปลี่ยนแปลงไปหลายชุดของอัลกอริทึมทั่วไป วิธีการเชิงวัตถุจะสร้างนามธรรมของอัลกอริทึมเป็นคลาสที่ห่อหุ้มและนำกลับมา ใช้ใหม่ได้ คลาสนี้เขียนขึ้นอย่างยืดหยุ่น โดยรองรับการสืบทอดและการโอเวอร์โหลด อย่างเต็มที่ เพื่อให้โค้ดที่เรียกใช้ทั้งหมดสามารถใช้โค้ดทั่วไปนี้ได้โดยตรง แทนที่จะเปลี่ยนแปลงโค้ดต้นฉบับ[ 4 ]เมื่อต้องการฟังก์ชันการทำงานเพิ่มเติม ไลบรารีจะถูกขยาย (ในขณะที่ยังคงรักษาความเข้ากันได้กับเวอร์ชันก่อนหน้า ) ด้วยวิธีนี้ หากอัลกอริทึมดั้งเดิมมีข้อบกพร่องที่ต้องแก้ไขหรือสามารถปรับปรุงได้ ซอฟต์แวร์ทั้งหมดที่ใช้ก็จะได้รับประโยชน์การเขียนโปรแกรมแบบทั่วไปมีเครื่องมือเพิ่มเติมในการสร้างนามธรรม
รหัสแยกสาขา
การแยกสาขาโค้ดเป็นส่วนหนึ่งของการพัฒนาซอฟต์แวร์โดยทีมขนาดใหญ่ ซึ่งช่วยให้สามารถพัฒนาแบบคู่ขนานบนทั้งสองสาขาได้ ส่งผลให้วงจรการพัฒนาสั้นลง การแยกสาขาแบบดั้งเดิมมีคุณสมบัติดังต่อไปนี้:
- มีการจัดการโดย ระบบ ควบคุมเวอร์ชันที่รองรับการสร้างสาขา
- เมื่อการพัฒนาแบบคู่ขนานเสร็จสมบูรณ์แล้ว สาขาต่างๆ จะถูกรวมเข้าด้วยกันอีกครั้ง
การคัดลอกและวางเป็นทางเลือกที่ไม่เป็นทางการมากนักเมื่อเทียบกับการแยกสาขาแบบดั้งเดิม มักใช้เมื่อคาดการณ์ว่าสาขาต่างๆ จะแตกแขนงออกไปมากขึ้นเรื่อยๆ เมื่อเวลาผ่านไป เช่น เมื่อมีการแยกผลิตภัณฑ์ใหม่จากผลิตภัณฑ์ที่มีอยู่เดิม
การเขียนโปรแกรมแบบคัดลอกและวางมีข้อดีอยู่บ้างในฐานะวิธีการแตกแขนงผลิตภัณฑ์ใหม่ เนื่องจากโครงการพัฒนาใหม่นี้ไม่แตะต้องโค้ดของผลิตภัณฑ์ที่มีอยู่เดิม:
- ไม่จำเป็นต้องทำการทดสอบการถดถอยกับผลิตภัณฑ์ที่มีอยู่แล้ว ซึ่งจะช่วยประหยัดเวลาในการควบคุมคุณภาพที่เกี่ยวข้องกับการเปิดตัวผลิตภัณฑ์ใหม่ และลด ระยะเวลาในการนำผลิตภัณฑ์ออก สู่ตลาด
- ไม่มีความเสี่ยงที่จะเกิดข้อผิดพลาดในผลิตภัณฑ์ที่มีอยู่ ซึ่งอาจสร้างความไม่พอใจให้กับผู้ใช้งานเดิม
ข้อเสียคือ:
- หากผลิตภัณฑ์ใหม่ไม่ได้แตกต่างจากผลิตภัณฑ์เดิมมากเท่าที่คาดการณ์ไว้ อาจจำเป็นต้องรองรับโค้ดสองชุด (ซึ่งมีค่าใช้จ่ายเป็นสองเท่า) ในขณะที่เดิมอาจใช้เพียงชุดเดียว สิ่งนี้อาจนำไปสู่การปรับโครงสร้างโค้ดและการรวมโค้ดด้วยตนเองที่สิ้นเปลืองในภายหลัง
- การ มีฐาน โค้ดที่ซ้ำกันจะทำให้เวลาที่ใช้ในการเปลี่ยนแปลงที่ต้องการในทั้งสองผลิตภัณฑ์เพิ่มขึ้นเป็นสองเท่า ซึ่งจะ ทำให้เวลาในการนำการเปลี่ยนแปลงเหล่านั้นออกสู่ตลาด นานขึ้นและอาจทำให้เวลาที่ประหยัดได้จากการแยกโค้ดตั้งแต่แรกนั้นหมดไปโดยสิ้นเชิง
เช่นเดียวกับข้างต้น ทางเลือกอื่นนอกเหนือจากวิธีการคัดลอกและวางคือวิธีการแบบแยกส่วน:
- เริ่มต้นด้วยการแยกโค้ดที่จะใช้ร่วมกันระหว่างทั้งสองผลิตภัณฑ์ออกเป็นไลบรารีต่างๆ
- ใช้ไลบรารีเหล่านั้น (แทนที่จะคัดลอกโค้ดเดิมมาอีกชุด) เป็นพื้นฐานในการพัฒนาผลิตภัณฑ์ใหม่
- หากมีการวางแผนผลิตภัณฑ์เวอร์ชันที่สาม สี่ หรือห้าเพิ่มเติมในอนาคต แนวทางนี้จะมีประสิทธิภาพมากกว่ามาก เนื่องจากไลบรารีโค้ดสำเร็จรูปจะช่วยลดระยะเวลาการพัฒนาผลิตภัณฑ์เพิ่มเติมหลังจากเวอร์ชันที่สองได้อย่างมาก[ 5 ]
งานที่ทำซ้ำๆ หรือรูปแบบต่างๆ ของงานเดิม

รูปแบบการเขียนโปรแกรมแบบคัดลอกและวางที่อันตรายที่สุดอย่างหนึ่ง เกิดขึ้นในโค้ดที่ทำซ้ำๆ หรือโค้ดที่ทำงานพื้นฐานเดียวกันแต่ต่างตัวแปรกัน แต่ละครั้งจะคัดลอกโค้ดจากด้านบนแล้ววางลงไปใหม่ โดยมีการแก้ไขเล็กน้อย ผลเสียที่เกิดขึ้น ได้แก่:
- วิธีการคัดลอกและวางมักนำไปสู่เมธอดที่มีขนาดใหญ่ (ซึ่งเป็นสัญญาณที่ไม่ดีของการเขียนโค้ด )
- แต่ละอินสแตนซ์จะสร้างโค้ดที่ซ้ำกัน โดยมีปัญหาทั้งหมดที่กล่าวถึงในส่วนก่อนหน้า แต่มีขอบเขตที่กว้างกว่ามาก การทำซ้ำหลายสิบรายการเป็นเรื่องปกติ และอาจมากถึงหลายร้อยรายการ การแก้ไขข้อผิดพลาดโดยเฉพาะจะทำได้ยากและมีค่าใช้จ่ายสูงมากในโค้ดดังกล่าว[ 6 ]
- โค้ดลักษณะนี้ยังมีปัญหาเรื่องความอ่านง่ายอย่างมาก เนื่องจากยากที่จะแยกแยะความแตกต่างระหว่างการทำซ้ำแต่ละครั้งได้อย่างแม่นยำ ซึ่งส่งผลโดยตรงต่อความเสี่ยงและต้นทุนในการแก้ไขโค้ด
- รูป แบบ การเขียนโปรแกรมเชิงขั้นตอนไม่สนับสนุนวิธีการคัดลอกและวางสำหรับงานที่ซ้ำซากอย่างยิ่ง ภายใต้รูปแบบเชิงขั้นตอน วิธีการที่เหมาะสมกว่าสำหรับงานที่ซ้ำซากคือการสร้างฟังก์ชันหรือรูทีนย่อยที่ดำเนินการผ่านงานเพียงครั้งเดียว จากนั้นรูทีนหลักจะเรียกรูทีนย่อยนี้ซ้ำๆ หรือจะดีกว่านั้นคือใช้โครงสร้างการวนซ้ำบางรูปแบบ โค้ดดังกล่าวเรียกว่า "มีการแบ่งส่วนที่ดี" และแนะนำให้ใช้เพราะอ่านง่ายกว่าและขยายได้ง่ายกว่า[ 7 ]
- หลักการทั่วไปที่ใช้ได้กับกรณีนี้คือ " อย่าพูดซ้ำซาก "
การเลือกออกแบบโดยเจตนา
การเขียนโปรแกรมแบบคัดลอกและวางนั้นบางครั้งก็ได้รับการยอมรับว่าเป็นเทคนิคการเขียนโปรแกรมที่ถูกต้อง โดยส่วนใหญ่จะพบเห็นได้ในโค้ดพื้นฐาน เช่น การประกาศคลาส หรือการนำเข้าไลบรารีมาตรฐาน หรือในการใช้แม่แบบโค้ดที่มีอยู่แล้ว (ที่มีเนื้อหาว่างเปล่าหรือฟังก์ชันจำลอง) เป็นกรอบในการเติมเต็ม
การใช้สำนวนการเขียนโปรแกรมและรูปแบบการออกแบบนั้นคล้ายกับการเขียนโปรแกรมแบบคัดลอกและวาง เนื่องจากก็ใช้โค้ดที่เป็นสูตรสำเร็จเช่นกัน ในบางกรณี อาจแสดงออกมาในรูปแบบของโค้ดสั้นๆ ซึ่งสามารถนำไปวางใช้ได้เมื่อต้องการ หรือบ่อยครั้งที่โปรแกรมเมอร์นึกโค้ดนั้นขึ้นมาเองจากความทรงจำ ในบางกรณี สำนวนการเขียนโปรแกรมไม่สามารถลดทอนให้เหลือเป็นแม่แบบโค้ดได้ อย่างไรก็ตาม ในกรณีส่วนใหญ่ แม้ว่าสำนวนการเขียนโปรแกรมจะสามารถลดทอนให้เหลือเป็นโค้ดได้ แต่โค้ดนั้นก็จะยาวมากพอที่จะต้องแยกออกมาเป็นฟังก์ชัน หรือสั้นพอที่จะพิมพ์ลงไปได้โดยตรง
ภาษาโปรแกรม Subtextเป็นโครงการวิจัยที่มีจุดมุ่งหมายเพื่อ "ลดความผิด" ของการคัดลอกและวาง โดยใช้ภาษานี้ การคัดลอกและวางเป็นรูปแบบการโต้ตอบหลัก และด้วยเหตุนี้จึงไม่ถือว่าเป็นรูปแบบที่ไม่พึงประสงค์
ตัวอย่าง
ตัวอย่างง่ายๆ คือลูป forซึ่งสามารถเขียนได้ดังนี้ for(inti=0;i!=n;++i){}
ตัวอย่างโค้ดที่ใช้ลูป for ดังกล่าวอาจเป็นดังนี้:
void foo ( int n ) { for ( int i = 0 ; i != n ; ++ i ) { /* body */ } }โค้ดสำหรับการวนซ้ำสามารถสร้างขึ้นได้โดยใช้โค้ดตัวอย่างต่อไปนี้ (โดยระบุประเภทและชื่อตัวแปร):
for ( $type $loop_var = 0 ; $loop_var != $stop ; ++ $loop_var ) { /* body */ }ดูเพิ่มเติม
ลิงก์ภายนอก
- c2:การเขียนโปรแกรมแบบคัดลอกและวาง
- แอนเดรย์ คาร์ปอฟผลที่ตามมาจากการใช้วิธีคัดลอกและวางในการเขียนโปรแกรม C++ และวิธีรับมือกับผลที่ตามมา
- อันเดรย์ คาร์ปอฟผลกระทบของบรรทัดสุดท้าย
- โปรแกรมตรวจจับการคัดลอก/วางของ PMD (CPD)
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ การเขียนโปรแกรมแบบคัดลอกและวาง
การเขียนโปรแกรมแบบคัดลอกและวาง หรือบางครั้งเรียกว่า การวาง เฉยๆ นั้น คือการสร้าง โค้ด โปรแกรมคอมพิวเตอร์ ที่ซ้ำซากมาก โดยใช้ การคัดลอกและวาง โดย ส่วนใหญ่แล้วคำนี้มีความหมายเชิงลบ...
ต้นกำเนิด
การเขียนโปรแกรมแบบคัดลอกและวางมักทำโดยโปรแกรมเมอร์ที่ไม่มีประสบการณ์หรือนักเรียน ซึ่งพบว่าการเขียนโค้ดตั้งแต่ต้นเป็นเรื่องยากหรือน่าหงุดหงิด...
การทำซ้ำ
ปรับปรุง โค้ดที่ซ้ำซ้อนโดยใช้ กลไก นามธรรม เช่น ฟังก์ชัน
การนำโค้ดไลบรารีไปใช้
การคัดลอกและวางยังทำโดยโปรแกรมเมอร์ที่มีประสบการณ์ ซึ่งมักจะมีไลบรารีของโค้ดสำเร็จรูปและ อัลกอริธึม ทั่วไปที่ผ่านการทดสอบมาอย่างดีและพร้อมใช้งานซึ่งสามารถปรับให้เข้ากับงานเฉพาะได้อย่างง่ายดาย [ 2 ]