ป้องกันโค้ดที่ไม่สนับสนุนจากการรวบรวมหลังจากถึงกำหนดเวลา [ปิด]


68

ในทีมของฉันเราได้ทำความสะอาดสิ่งเก่า ๆ มากมายในโครงการเสาหินขนาดใหญ่ (ทั้งชั้นเรียนวิธีการและอื่น ๆ )

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

ฉันค้นหาในอินเทอร์เน็ตและไม่พบสิ่งใดที่มีความสามารถตามที่อธิบายไว้ด้านล่าง:

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

ฉันคิดว่าฉันกำลังค้นหายูนิคอร์น ... มีเทคโนโลยีที่คล้ายคลึงกันสำหรับภาษาโปรแกรมใด ๆ หรือไม่?

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


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

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

53
นั่นฟังดูเหมือนยูนิคอร์นที่ชั่วร้ายจริงๆ คุณมีซอฟต์แวร์นิดหน่อยที่คอมไพล์ได้ดีผ่านการทดสอบทั้งหมดและคุณส่งไปให้ลูกค้า จากนั้นวันหนึ่งคุณลองตรวจสอบซอฟต์แวร์อีกครั้งและมันจะไม่สร้างแม้แต่บนแพลตฟอร์มการพัฒนาเดียวกัน ตอนนี้คุณถูกบังคับให้แก้ไขโค้ดที่ผ่านการทดสอบอย่างเป็นทางการหรือทำแฮ็กที่ชั่วร้ายเช่นการย้อนเวลานาฬิกาของคอมพิวเตอร์
Simon B

6
ทำให้เป็น @ Deprecated_RemoveMe_2018_06_01 จากนั้นในวันที่ 2018-06-01 ให้ลบคำอธิบายประกอบออก Voila รหัสของคุณทั้งหมดที่ใช้คำอธิบายประกอบจะไม่รวบรวมอีกต่อไป! (เนื่องจากไม่พบคำอธิบายประกอบ)
user253751

65
หลายปีในอนาคตผู้พัฒนาที่ได้รับการว่าจ้างใหม่จะถามว่า: ทำไมเวลาสร้างเซิร์ฟเวอร์ตั้งถึงมกราคม 2559 และคนที่อยู่ที่นั่นเป็นเวลา 10 ปีจะบอกเขาว่ามันจำเป็นหรืองานสร้างแตกในที่สุ่ม ถอนหายใจ
Wilbert

คำตอบ:


62

ฉันไม่คิดว่านี่จะเป็นคุณสมบัติที่มีประโยชน์เมื่อห้ามการรวบรวมจริงๆ เมื่อวันที่ 01/06/2018 ส่วนใหญ่ของรหัสจะไม่รวบรวมซึ่งรวบรวมไว้เมื่อวันก่อนทีมของคุณจะลบคำอธิบายประกอบนั้นอย่างรวดเร็วอีกครั้งโค้ดจะถูกล้างข้อมูลหรือไม่

อย่างไรก็ตามคุณสามารถเพิ่มคำอธิบายประกอบที่กำหนดเองให้กับรหัสเช่น

@Deprecated_after_2018_07_31

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

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


9
@Bergi: เฮ้นี่เป็นเพียงตัวอย่าง OP สามารถใช้เวอร์ชันหรือแท็กวันที่สิ่งที่พวกเขาต้องการในการควบคุมของพวกเขา
Doc Brown

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

4
@ jpaugh ฉันขอแนะนำไม่ให้จมชั่วโมง (หมายเหตุ, เวลา = เงิน) ในการสร้างเครื่องมือใหม่เพื่อทำงานที่คุณสามารถทำได้อย่างมีประสิทธิภาพด้วยเครื่องมือที่มีอยู่แล้วไม่ว่าเครื่องมือเหล่านั้นจะเป็นอะไรก็ตาม
jpmc26

3
@ jpmc26: ฉันเห็นข้อดีสองประการ (เล็ก): ไม่ได้รับคำเตือนการคัดแยกจำนวนมาก (ซึ่งจะทำให้เกิดความเสี่ยงในการมองเห็นสิ่งที่สำคัญกว่า) และความเป็นไปได้ในการนำเสนอเกณฑ์การคัดแยกประเภทที่แตกต่างกัน ยิ่งไปกว่านั้น OP ยังถามอย่างชัดเจนว่ามีเพศสัมพันธ์กับวันที่ใด
Doc Brown

7
ฉันจะ +1 ถ้าคุณจะใช้คำสั่ง YYYY-MM-DD สำหรับวันที่ในตัวอย่างของคุณเพราะฉันเคยเห็นความคลุมเครือเพียงอย่างเดียว - - - - คำสั่ง YYYY ทำให้เกิดความเจ็บปวดและความเข้าใจผิด
mtraceur

284

นี้จะเป็นคุณลักษณะที่เรียกว่าระเบิดครั้ง อย่าสร้างระเบิดเวลา

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

ดูด้วยวิธีนี้: ถ้าคุณจัดระเบียบและตระหนักถึงรหัสพื้นฐานของคุณเพียงพอที่คุณใส่ใจเกี่ยวกับความล้าสมัยและติดตามมันคุณไม่จำเป็นต้องมีกลไกภายในรหัสเพื่อเตือนให้คุณทราบ หากคุณไม่เป็นไปได้ว่าคุณยังไม่ได้รับข้อมูลล่าสุดในด้านอื่น ๆ ของฐานรหัสและอาจไม่สามารถตอบสนองต่อการเตือนภัยได้ทันเวลาและถูกต้อง กล่าวอีกนัยหนึ่งการทิ้งระเบิดครั้งไม่เหมาะสำหรับใครก็ตาม เพียงแค่บอกว่าไม่!


74
+1 สิ่งนี้จะกัดคุณ หลายเดือนต่อมา. ในวันศุกร์เช่นเดียวกับที่คุณกำลังพยายามติดตั้งฉุกเฉิน และเป็นวันหยุดยาวดังนั้นทุกคนที่รู้อะไรเกี่ยวกับมันจะออกจากสำนักงาน อย่าทำมัน
Roger Lipscombe

3
ตกลง. ล้าสมัยเป็นปัญหาขององค์กรไม่ใช่ปัญหาการเข้ารหัส ฉันยังคงสามารถเสียบแอปเปิ้ล] [และเขียนพื้นฐานไม่มีอะไรหยุดฉันได้ แต่ผมจะต้องการหรือไม่

19
ทางออกที่ถูกต้องซึ่งไปในทิศทาง "จัดระเบียบและรับรู้" ของคุณคือการเพิ่มบั๊กในระบบติดตามบั๊กของคุณโดยพูดว่า "ลบ <เช่นและ>>" พร้อมกรอบเวลาที่แนะนำไว้ในความคิดเห็น และในอีก 6 เดือนเมื่อมีการตรวจสอบข้อผิดพลาดเพื่อค้นหาว่ามีข้อบกพร่องใดบ้างที่ควรได้รับการแก้ไขในรุ่นถัดไปหากกรอบเวลานั้นใกล้เข้ามาคุณพูดว่า "ถึงเวลาแล้วที่จะทำสิ่งนี้" มันคือการจัดการโครงการขั้นพื้นฐาน
การแข่งขัน Lightness ใน Orbit

1
ในความเป็นจริงหากกำหนดการวางจำหน่ายของคุณสามารถคาดการณ์ได้อย่างเพียงพอ
การแข่งขัน Lightness ใน Orbit

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

70

ใน C # คุณจะใช้ObsoleteAttributeในลักษณะต่อไปนี้:

  • ในเวอร์ชัน 1 คุณจัดส่งฟีเจอร์นี้ วิธีการเรียนอะไรก็ตาม
  • ในเวอร์ชัน 2 คุณจัดส่งฟีเจอร์ที่ดีกว่าเพื่อแทนที่ฟีเจอร์ดั้งเดิม คุณใส่แอตทริบิวต์เลิกใช้ในคุณลักษณะตั้งเป็น "คำเตือน" และให้ข้อความที่ระบุว่า "ฟีเจอร์นี้เลิกใช้แล้วใช้ฟีเจอร์ที่ดีกว่าแทนในเวอร์ชัน 3 ของไลบรารีนี้ซึ่งจะเปิดตัวเช่นนี้ วันที่การใช้งานคุณสมบัตินี้จะเป็นข้อผิดพลาด " ขณะนี้ผู้ใช้คุณลักษณะยังสามารถใช้งานได้ แต่มีเวลาในการอัปเดตรหัสเพื่อใช้คุณสมบัติใหม่
  • ในเวอร์ชัน 3 คุณอัปเดตแอททริบิวให้เป็นข้อผิดพลาดแทนที่จะเป็นการเตือนและอัปเดตข้อความเพื่อบอกว่า "ฟีเจอร์นี้เลิกใช้แล้วใช้ฟีเจอร์ที่ดีกว่าแทนในเวอร์ชั่น 4 ของไลบรารี่นี้ วันที่คุณสมบัตินี้จะโยน " ผู้ใช้ที่ไม่ปฏิบัติตามคำเตือนก่อนหน้าของคุณยังคงได้รับข้อความที่มีประโยชน์ที่บอกพวกเขาถึงวิธีการแก้ไขปัญหาและพวกเขาต้องแก้ไขเพราะตอนนี้รหัสของพวกเขาไม่ได้รวบรวม
  • ในเวอร์ชัน 4 คุณเปลี่ยนคุณสมบัติเพื่อให้มีข้อยกเว้นร้ายแรงบางอย่างและเปลี่ยนข้อความเพื่อบอกว่าคุณลักษณะนั้นจะถูกลบทั้งหมดในเวอร์ชันถัดไป
  • ในเวอร์ชัน 5 คุณลบฟีเจอร์ทั้งหมดและถ้าผู้ใช้บ่นเอาล่ะคุณให้คำเตือนอย่างยุติธรรมสามรอบและพวกเขาสามารถใช้เวอร์ชัน 2 ต่อไปได้เสมอหากพวกเขารู้สึกอย่างจริงจัง

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


2
ฉันเชื่อว่านี่เป็นวิธีการที่ถูกต้อง แต่ฉันจะเปลี่ยนสิ่งหนึ่ง ... ที่จะเปลี่ยน "ถ้าผู้ใช้บ่น" เป็น "เมื่อผู้ใช้บ่น"
Liath

10
การลบเนื้อหาในเวลาเดียวกันเมื่อเปลี่ยนไปเป็นข้อผิดพลาดดูเหมือนว่าผิดปกติ ข้อดีอย่างหนึ่งของข้อผิดพลาดของเวอร์ชันที่ถูกปฏิเสธคือช่วยให้โค้ดที่สร้างขึ้นจากเวอร์ชันก่อนหน้านี้ยังคงทำงานต่อไปในขณะที่ป้องกันโค้ดที่คอมไพล์ใหม่จากการใช้งาน ดังนั้นคุณยังคงเข้ากันได้กับ ABI ในขณะที่จงใจทำลาย API ที่เข้ากันได้ แน่นอนว่าโลกที่สมบูรณ์แบบนั้นคุณจะต้องมีการกำหนดเวอร์ชันของ semver style เป็นต้นซึ่งคุณจะไม่เรียกใช้โค้ดใหม่ด้วยแอพพลิเคชั่นที่รวบรวมไว้ก่อนหน้านี้
Kevin Cathcart

@KevinCathcart: นั่นเป็นประเด็นที่ดี อาจจะเป็นอีกขั้นหนึ่งในนั้น! ฉันจะอัปเดตข้อความ
Eric Lippert

1
ที่จริงแล้วถ้าคุณกำลังทำ SemVer คุณสามารถตรงจากเลิกใช้ในรุ่น XY0 (การคัดค้านใด ๆ จะต้องเป็นรุ่นย่อย) เพื่อลบออกอย่างสมบูรณ์ใน X + 1.0.0 ฉันว่ามันดีที่จะชะลออีกสักหน่อย (ถึง X + 2.0.0?) แต่กระบวนการห้าขั้นตอนนี้น่าจะทำให้ดอกลิลลี่ ขั้นตอนถัดไปหลังจาก "คำเตือน" ควรเป็น "ข้อผิดพลาดร้ายแรง" (เนื่องจากคุณลักษณะที่เลิกใช้แล้วจะถูกแทนที่ด้วยรหัสที่ทำให้เกิดข้อผิดพลาด) เนื่องจากlibfoo.so.2และlibfoo.so.3สามารถอยู่ร่วมกันได้เป็นอย่างดีดาวน์สตรีมของคุณสามารถใช้ไลบรารีเก่าต่อไปจนกว่าพวกเขาจะได้สลับ
Monty Harder

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

24

คุณเข้าใจผิดว่า "เลิก" หมายความว่าอย่างไร วิธีการเลิกใช้:

ใช้งานได้ แต่ถือว่าล้าสมัยและหลีกเลี่ยงได้ดีที่สุดโดยทั่วไปเพราะถูกแทนที่

พจนานุกรมออกฟอร์ด

ตามคำนิยามคุณสมบัติที่เลิกใช้จะยังคงรวบรวม

คุณกำลังจะลบสถานที่ในวันที่กำหนด ไม่เป็นไร. วิธีที่คุณทำคือลบออกในวันนั้น

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


สนใจในสิ่งที่ผู้ลงคะแนนไม่เห็นด้วย
jpmc26

2
+1 หากคุณใช้ JIRA เพื่อการพัฒนาแบบคล่องตัวให้สร้างงานและวางมันลงในการวิ่งในอนาคต ปรับให้เข้ากับเครื่องมือและวิธีการจัดการโครงการอื่น ๆ ที่คุณติดตาม วิธีนี้แก้ไขได้ดีที่สุดด้วยวิธีที่ไม่ใช่ด้านเทคนิค
Matthew อ่าน

1
และตรวจสอบให้แน่ใจ Class / Lib ยังคงอยู่ในเอกสารเป็นค่าเสื่อมราคาและ / หรือลบออกในรุ่น Xx
Phil M

12

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

นอกจากนี้ดูเหมือนว่าวิธีแก้ปัญหาเล็กน้อยเพื่อตั้งนาฬิกาของเครื่องของฉันกลับไปหนึ่งหรือสองปีก่อนที่จะรวบรวม

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

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


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

6

ฉันไม่เคยเห็นคุณลักษณะดังกล่าวมาก่อน - คำอธิบายประกอบที่เริ่มมีผลบังคับใช้หลังจากวันที่ระบุ

อย่างไรก็ตาม@Deprecatedก็เพียงพอแล้ว จับคำเตือนใน CI และทำให้มันปฏิเสธที่จะยอมรับการสร้างหากมีอยู่ สิ่งนี้จะเปลี่ยนความรับผิดชอบจากคอมไพเลอร์ไปยัง build ไปป์ไลน์ของคุณ แต่มีข้อดีที่คุณสามารถ (semi) ได้อย่างง่ายดายเปลี่ยน build ไปป์ไลน์โดยการเพิ่มขั้นตอนเพิ่มเติม

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


4

คุณกำลังมองหาปฏิทินหรือรายการสิ่งที่ต้องทำ

อีกทางเลือกหนึ่งคือการใช้คำเตือนคอมไพเลอร์ที่กำหนดเองหรือข้อความคอมไพเลอร์ถ้าคุณจัดการให้มีน้อยถ้าคำเตือนใด ๆ ใน codebase ของคุณ หากคุณมีคำเตือนมากเกินไปคุณจะต้องใช้ความพยายามเพิ่มเติม (ประมาณ 15 นาที?) และต้องรับคำเตือนคอมไพเลอร์ในรายงานบิลด์ที่การรวมระบบอย่างต่อเนื่องของคุณส่งไปในแต่ละบิลด์

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

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


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

3

วิธีหนึ่งในการคิดเกี่ยวกับสิ่งนี้คือสิ่งที่คุณหมายถึงตามเวลา / วันที่ ? คอมพิวเตอร์ไม่ทราบว่าแนวคิดเหล่านี้คืออะไรพวกเขาจะต้องมีการตั้งโปรแกรมอย่างใด เป็นเรื่องปกติที่จะแสดงเวลาในรูปแบบ UNIX เป็น "วินาทีนับตั้งแต่ยุค" และเป็นเรื่องปกติที่จะป้อนค่าเฉพาะลงในโปรแกรมผ่านการเรียกใช้ระบบปฏิบัติการ อย่างไรก็ตามไม่ว่าการใช้งานนี้จะเป็นเรื่องธรรมดาเพียงใดก็ตามโปรดทราบว่าไม่ใช่เวลา "จริง": เป็นเพียงการแสดงเชิงตรรกะ

ตามที่คนอื่น ๆ ได้ชี้ให้เห็นหากคุณสร้าง "กำหนดเวลา" โดยใช้กลไกนี้มันสำคัญมากที่จะเลี้ยงในเวลาที่ต่างออกไปและทำลาย "กำหนดเวลา" นั้น เช่นเดียวกันกับกลไกที่ซับซ้อนยิ่งขึ้นเช่นการขอเซิร์ฟเวอร์ NTP (แม้ผ่านการเชื่อมต่อที่ "ปลอดภัย" เนื่องจากเราสามารถแทนที่ใบรับรองของเราเอง, ผู้ออกใบรับรองหรือแม้แต่แก้ไขไลบรารี crypto) ตอนแรกมันอาจปรากฏว่าบุคคลดังกล่าวมีความผิดสำหรับการทำงานรอบกลไกของคุณ แต่มันอาจจะเป็นกรณีที่มันทำโดยอัตโนมัติและสำหรับเหตุผลที่ดี ตัวอย่างเช่นเป็นความคิดที่ดีที่จะมีบิลด์ที่ทำซ้ำได้และเครื่องมือที่จะช่วยให้สิ่งนี้อาจรีเซ็ต / สกัดกั้นการเรียกระบบที่ไม่ได้กำหนดไว้โดยอัตโนมัติ libfaketimeทำอย่างนั้นตั้งค่าการประทับเวลาของไฟล์ทั้งหมดเป็นคุณสมบัติการบันทึก / เล่นซ้ำ1970-01-01 00:00:01ของ Qemu ทำให้การโต้ตอบของฮาร์ดแวร์ทั้งหมด ฯลฯ

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

มีตัวแทนเชิงตรรกะอื่น ๆ ของเวลา: หนึ่งในนั้นคือรุ่นของซอฟต์แวร์ (ทั้งแอพของคุณหรือการพึ่งพาบางส่วน) นี่เป็นการนำเสนอที่ต้องการมากขึ้นสำหรับ "กำหนดเวลา" มากกว่าเช่นเวลา UNIX เนื่องจากมันมีความเฉพาะเจาะจงมากขึ้นกับสิ่งที่คุณสนใจ (การเปลี่ยนชุดคุณลักษณะ / APIs) และดังนั้นจึงมีโอกาสน้อยที่จะเหยียบย่ำความกังวลแบบมุมฉาก การทำงานตามกำหนดเวลาของคุณอาจสิ้นสุดการทำลายไฟล์บันทึกงาน cron งานแคช ฯลฯ )

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

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

คำถามสำคัญเกี่ยวกับวิธีการ "ดึง" คือเวอร์ชั่นอ้างอิงนั้นนับว่าเป็น "หน่วย" ( ของฟังก์ชัน ) หรือไม่ดังนั้นจึงสมควรได้รับการทดสอบ หรือไม่ว่าจะเป็นเพียงรายละเอียดการใช้งาน "ส่วนตัว" ซึ่งควรใช้เป็นส่วนหนึ่งของการทดสอบหน่วย ( ของฟังก์ชัน ) จริงเท่านั้น ฉันจะบอกว่า: หากความแตกต่างระหว่างเวอร์ชันของการพึ่งพานั้นนับเป็นคุณสมบัติของแอปพลิเคชันของคุณจริงๆให้ทำการทดสอบ (ตัวอย่างเช่นการตรวจสอบว่าเวอร์ชัน Python นั้นเป็น> = 3.x) ถ้าไม่เช่นนั้นไม่ได้เพิ่มการทดสอบ (เนื่องจากจะมีความเปราะไม่เป็นทางการและเข้มงวดมากเกินไป) หากคุณควบคุมห้องสมุดให้ไปตามเส้นทาง "push" หากคุณไม่ได้ควบคุมไลบรารีให้ใช้เวอร์ชันใดก็ได้ที่มีให้: หากการทดสอบของคุณผ่านไปแล้วก็ไม่คุ้มค่าที่จะ จำกัด ตัวเอง หากพวกเขาไม่ผ่านก็เป็น "วันสุดท้าย" ของคุณที่นั่น!

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

แต่ละเหล่านี้จะสามารถใช้งานได้ในสถานการณ์ที่แตกต่างกัน


1

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

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


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

1

ข้อกำหนดหนึ่งคือการแนะนำแนวคิดเกี่ยวกับเวลาในการสร้าง ใน C, C ++ หรือภาษาอื่น ๆ / สร้างระบบที่ใช้ C-เช่น preprocessor 1ใครจะแนะนำการประทับเวลาผ่านกำหนดสำหรับ preprocessor CPPFLAGS=-DTIMESTAMP()=$(date '+%s')เวลาที่สร้างไปนี้: สิ่งนี้น่าจะเกิดขึ้นใน makefile

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

#if TIMESTAMP() == 0 || TIMESTAMP() > 1520616626
#   error "The time for this feature has run out, sorry"
#endif

อีกวิธีหนึ่งสามารถ "กำหนด" รหัสที่เป็นปัญหาเมื่อถึงเวลา ที่จะอนุญาตให้โปรแกรมรวบรวมหากไม่มีใครใช้งาน สมมติว่าเรามีส่วนหัวที่กำหนด api "api.h" และเราไม่อนุญาตให้โทรold()หลังจากเวลาใดเวลาหนึ่ง:

//...
void new1();
void new2();
#if TIMESTAMP() < 1520616626
   void old();
#endif
//...

โครงสร้างที่คล้ายกันอาจจะกำจัดold()ฟังก์ชันของฟังก์ชันออกจากไฟล์ต้นฉบับบางไฟล์

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

เห็นได้ชัดว่าใช้งานได้เฉพาะเมื่อไลบรารีถูกรวบรวมใหม่ - หลังจากนั้นรหัสที่ล้าสมัยก็ไม่มีอยู่ในห้องสมุดอีกต่อไป มันจะไม่ป้องกันรหัสลูกค้าจากการเชื่อมโยงไปยังไบนารีที่ล้าสมัยแม้ว่า


1 C # รองรับคำจำกัดความง่ายๆของสัญลักษณ์พรีโปรเซสเซอร์ไม่มีค่าตัวเลขซึ่งทำให้กลยุทธ์นี้ใช้ไม่ได้


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

@mindriot นั่นเป็นแง่มุมที่น่าสนใจ ฉันคิดว่ามันเป็นความจริงกับทุกวิธีที่นำความคิดเกี่ยวกับเวลามาใช้กับรหัส - OP กล่าวอย่างชัดเจนว่า "หลังจากผ่านวันที่ระบุ" หนึ่งสามารถจัดการด้านเวลาในระบบการสร้างแม้ว่าและปล่อยให้รหัสเพียงอย่างเดียวจริง แต่ OP ขออย่างชัดเจนสำหรับ "สิ่งที่ใส่ไว้ในรหัส" โซลูชันของฉันมีความได้เปรียบในการเป็นอิสระจากวิธีการสร้างใด ๆ โดยเฉพาะ มันสามารถถูกโกงได้ แต่คุณต้องทำอย่างใดอย่างหนึ่งไม่ทางใดก็ทางหนึ่ง
Peter - Reinstate Monica

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

0

ใน Visual Studio คุณสามารถตั้งค่าสคริปต์ที่สร้างไว้ล่วงหน้าซึ่งส่งข้อผิดพลาดหลังจากวันที่กำหนด สิ่งนี้จะป้องกันการรวบรวม นี่คือสคริปต์ที่ส่งข้อผิดพลาดในหรือหลังวันที่ 12 มีนาคม 2018 ( นำมาจากที่นี่ ):

@ECHO OFF

SET CutOffDate=2018-03-12

REM These indexes assume %DATE% is in format:
REM   Abr MM/DD/YYYY - ex. Sun 01/25/2015
SET TodayYear=%DATE:~10,4%
SET TodayMonth=%DATE:~4,2%
SET TodayDay=%DATE:~7,2%

REM Construct today's date to be in the same format as the CutOffDate.
REM Since the format is a comparable string, it will evaluate date orders.
IF %TodayYear%-%TodayMonth%-%TodayDay% GTR %CutOffDate% (
    ECHO Today is after the cut-off date.
    REM throw an error to prevent compilation
    EXIT /B 2
) ELSE (
    ECHO Today is on or before the cut-off date.
)

อย่าลืมอ่านคำตอบอื่น ๆ ในหน้านี้ก่อนที่จะใช้สคริปต์นี้


-1

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

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

สำหรับโซลูชันที่อิง SCM ฉันจะสมมติว่าคุณใช้ git และ git-flow (ถ้าไม่ใช่ตรรกะสามารถปรับให้เข้ากับ VCS อื่นได้อย่างง่ายดาย) postDeprecatedสร้างสาขาใหม่ ในสาขานั้นลบรหัสที่ไม่สนับสนุนทั้งหมดและเริ่มทำงานในการลบการอ้างอิงใด ๆ จนกว่าจะรวบรวม การเปลี่ยนแปลงปกติใด ๆ จะดำเนินต่อไปยังmasterสาขา ทำการผสานการเปลี่ยนแปลงรหัสที่เกี่ยวข้องที่ไม่ได้รับการสนับสนุนmasterย้อนกลับไปpostDeprecatedเพื่อลดความท้าทายในการรวม

หลังจากวันที่สิ้นสุดการเลิกสร้างใหม่สาขาจากpreDeprecated masterแล้วรวมกลับเข้ามาpostDeprecated masterถ้าปล่อยของคุณออกไปจากmasterสาขาคุณควรจะใช้สาขาหลังเลิกใช้หลังจากวันที่ หากมีเหตุฉุกเฉินหรือคุณไม่สามารถส่งผลลัพธ์ได้ทันเวลาคุณสามารถย้อนกลับไปที่preDeprecatedและทำการเปลี่ยนแปลงใด ๆ ที่จำเป็นในสาขานั้น


7
วิธีการดังกล่าวดูเหมือนฝันร้ายจิสติกส์ หากคุณเริ่มรักษาสาขาคู่ขนานที่ใกล้เคียงกันคุณจะต้องเสียเวลาไปกับการทำเช่นนั้น เสียรวม
การแข่งขัน Lightness ใน Orbit

6
ฉันไม่สามารถตกลงได้ว่าการบำรุงรักษาสาขาคู่ขนานโดยใช้เพียงหนึ่งฟังก์ชันเพื่อลบฟังก์ชันที่เลิกใช้แล้วหลายรุ่นก่อนที่คุณจะต้องการลบออกจากผลิตภัณฑ์จริง ๆ ก็คือ "มาตรฐานอุตสาหกรรม" จุดประสงค์ของสิ่งนั้นคืออะไร? ใช่ VCS สามารถทำการผสานบางอย่างโดยอัตโนมัติ แต่ควรทำการผสานด้วยสายตาของนักพัฒนาเพื่อแก้ไขข้อขัดแย้งทางตรรกะ (และจะเกิดอะไรขึ้นเมื่อคุณได้รับข้อขัดแย้งที่ไม่สามารถแก้ไขได้ด้วยคำศัพท์) การมีระบบบิลด์ผสานกันโดยพลการทุกวันสำหรับสิ่งนี้เป็นเพียง ... ไร้จุดหมาย ลบคุณลักษณะเมื่อถึงเวลาที่จะลบออก
การแข่งขัน Lightness ใน Orbit

3
เนื่องจากมีเหตุผลที่ดีในการรักษาการเปิดสาขา (backporting patch ที่สำคัญ) ไม่มีเหตุผลที่ดีที่จะรักษาสาขา "สิ่งที่ฉันอาจทำในอนาคต" มันไม่มีค่าใช้จ่ายเลย เรียบง่ายเหมือนที่
การแข่งขัน Lightness ใน Orbit

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

2
@lightness - มีหลายเหตุผลที่ทำไมการเลิกใช้รหัสอย่างเป็นทางการไม่ได้เป็นเพียง "สิ่งที่เราอาจทำเมื่อใดก็ตามที่เราไปถึง" บางทีรหัสที่เลิกใช้แล้วอาจใช้ห้องสมุดซึ่งมีการทิ้งการสนับสนุนอย่างเป็นทางการ รหัสที่เลิกใช้แล้วอาจเป็น IP ที่ใบอนุญาตหมดอายุหลังจากวันที่กำหนดไว้ บางทีหลังจากวันที่กำหนดมีกฎระเบียบใหม่และรหัสไม่เป็นไปตาม ทางออกของคุณดีและดีถ้าคุณอาศัยอยู่ในหอคอยงาช้าง แต่องค์กรในโลกแห่งความเป็นจริงจะจัดการกับสถานการณ์ประเภทนี้ตลอดเวลา ซอฟต์แวร์ต้องตอบสนองความต้องการของธุรกิจไม่ใช่ในทางกลับกัน
79126
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.