ควรอัปเดตรหัสที่เก่ากว่าเพื่อใช้โครงสร้างภาษาใหม่หรือควรสร้างโครงสร้างที่ล้าสมัยหรือไม่?


15

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

ฉันควร:

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

1
@JerryCoffin ฉันจะไม่โต้เถียงในความคิดเห็น: ฉันโพสต์ในเมตาที่เราสามารถมีการสนทนาที่เหมาะสม

คำตอบ:


10

มันเป็นไปไม่ได้ที่จะให้คำตอบที่ชัดเจนสำหรับคำถามนี้เพราะมันขึ้นอยู่กับรายละเอียดของสถานการณ์

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

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

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


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

3
@AnandVaidya: นั่นเป็นความคาดหวังที่ไม่สมจริงของ IMHO เนื่องจากมันถือว่าโค้ดเก่าตาม OCP หรือสามารถเปลี่ยนแปลงได้ง่ายเพื่อติดตาม OCP ซึ่งไม่ค่อยเป็นกรณีหรือไม่คุ้มค่ากับความพยายาม
Doc Brown

1
เมื่อฉันพูดว่า ocp ฉันไม่ได้หมายถึง oops ocp แต่เป็น ocp โดยทั่วไป โดยทั่วไปแล้วพยายามอย่าแก้ไขรหัสที่มีอยู่ให้มากที่สุดและแยกรหัสของคุณเอง ที่เป็นไปได้ด้วยรหัสขั้นตอนเก่า ฉันเข้าใจว่ารหัสสปาเก็ตตี้ไม่สามารถแก้ไขได้ด้วยวิธีนี้ แต่สำหรับรหัสที่ออกแบบมาอย่างดีในกระบวนทัศน์ใด ๆ การปิดแบบเปิดควรใช้งานได้ง่าย อาจเป็นโอ๊ะโอหรือขั้นตอนหรือการทำงาน
Anand Vaidya

2
@AnandVaidya: เมื่อคุณไม่ได้หมายถึง OCP คุณไม่ควรเรียกมันอย่างนั้น ฉันเดาว่าคุณหมายถึงอะไรจริง ๆ คือสิ่งที่การเรียกของ Feather กำลังเขียนโค้ดใหม่ในวิธีการแตกหน่อดังนั้นเราจึงสามารถ จำกัด รูปแบบโค้ดใหม่เป็นวิธีที่แยกใหม่ เมื่อเป็นไปได้และสมเหตุสมผลคุณก็ถูกต้องแล้วก็โอเค น่าเสียดายที่วิธีการนี้ใช้ไม่ได้เสมอไปอย่างน้อยก็ไม่ใช่ถ้าคุณต้องการเก็บรหัสเก่าไว้
Doc Brown

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

5

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

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

หากคุณไม่สามารถรับประกันความมั่นคงนั้นได้ (คุณยังไม่ได้รับการทดสอบเหล่านั้น) ให้ปล่อยให้อยู่คนเดียว

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

แน่นอนว่าไม่มีอะไรจะหยุดคุณสร้างชุดการทดสอบดังกล่าวในความพร้อมสำหรับการออกกำลังกาย ...


4

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

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

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

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

ประเด็นสำคัญอีกข้อหนึ่ง: ตอนนี้ปรากฏโมดูลนี้มีการบำรุงรักษาน้อยที่สุดเป็นเวลานาน (แม้ว่าโครงการโดยรวมจะได้รับการดูแล) ซึ่งมีแนวโน้มที่จะบ่งบอกว่ามันเขียนได้ค่อนข้างดีและปราศจากข้อผิดพลาด - มิเช่นนั้นอาจมีการบำรุงรักษาเพิ่มขึ้นในระหว่างกาล

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

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

หากข้อกำหนดมีการเปลี่ยนแปลงคุณอาจต้องพิจารณาประเภทของการเปลี่ยนแปลงที่เกี่ยวข้องและสิ่งที่ขับเคลื่อนการเปลี่ยนแปลงนั้น ตัวอย่างเช่นสมมติว่าคุณกำลังแก้ไข Git เพื่อแทนที่การใช้ SHA-1 ด้วย SHA-256 นี่เป็นการเปลี่ยนแปลงข้อกำหนด แต่ขอบเขตมีการกำหนดไว้อย่างชัดเจนและค่อนข้างแคบ เมื่อคุณจัดเก็บและใช้ SHA-256 อย่างถูกต้องแล้วคุณไม่น่าจะพบกับการเปลี่ยนแปลงอื่น ๆ ที่มีผลต่อส่วนที่เหลือของรหัสฐาน

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

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


1

ฉันจะไปกับคุณตัวเลือกแรก เมื่อฉันรหัสฉันปฏิบัติตามกฎเพื่อให้มันอยู่ในสถานะที่ดีขึ้นแล้วมันเป็น

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


1

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

นอกจากนี้คุณยังต้องการหลีกเลี่ยงการฝังสองสไตล์ในฟังก์ชันเดียวกันมากกว่าที่คุณต้องการหลีกเลี่ยงภายในสองฟังก์ชันที่แยกกัน

ในการสรุป: การตัดสินใจขั้นสุดท้ายของคุณควรอยู่บนพื้นฐานของการวิเคราะห์ 'ต้นทุน' / 'ผลประโยชน์' ในกรณีของคุณ

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