ตู้เสื้อผ้าของ Barack Obama มีอะไรที่เหมือนกันกับประวัติ Git ที่ดี

Dec 02 2022
วันหนึ่งในฤดูร้อนช่วงปลายเดือนสิงหาคมของปี 2014 ประธานาธิบดีบารัค โอบามาในตอนนั้นได้ตัดสินใจเรื่องที่ทำให้ทั้งประเทศต้องตกตะลึง เขาสวมสูทที่แตกต่างออกไป ผลที่ตามมาคือ “การโต้เถียงเรื่องชุดสูทสีแทน” ได้ครอบงำวงจรข่าวและแพร่กระจายออกไปด้วยเหตุผลหลายประการ แต่ท้ายที่สุดแล้ว มันถูกกระตุ้นโดยความแปลกใหม่ของชุดสูทนั่นเอง

วันหนึ่งในฤดูร้อนช่วงปลายเดือนสิงหาคมของปี 2014 ประธานาธิบดีบารัค โอบามาในตอนนั้นได้ตัดสินใจเรื่องที่ทำให้ทั้งประเทศต้องตกตะลึง เขาสวมสูทที่แตกต่างออกไป ผลที่ตามมาคือ “ การโต้เถียงเรื่องชุดสูทสีแทน ” ได้ครอบงำวงจรข่าวและแพร่กระจายออกไปด้วยเหตุผลหลายประการ แต่ท้ายที่สุดแล้ว มันถูกจุดชนวนด้วยความแปลกใหม่ของชุดสูท เช่นเดียวกับเสื้อคอเต่าสีดำของ Steve Jobs และเสื้อเชิ้ตสีเทาของ Mark Zuckerberg โอบามามักจะใส่สูทสีน้ำเงินหรือเทา ซ้ำๆ กันทุกวัน

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

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

ประวัติเป็นของใคร?

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

คำนึงถึงสิ่งนี้ เป็นที่น่าสังเกตว่ามีคนสองประเภทกว้าง ๆ ที่ในบางจุดจะดูการกระทำเฉพาะ:

  1. ผู้ตรวจทานโค้ด
    ผู้ที่ดูการคอมมิตก่อนที่จะรวมเข้ากับประวัติโดยผ่านกระบวนการตรวจสอบโค้ด คนเหล่านี้มักเรียกกันว่า "ผู้ตรวจสอบโค้ด" ในทีมที่ดี ทุกคนจะเป็นผู้ตรวจสอบโค้ด และอาจมีหลายชุดสำหรับการเปลี่ยนแปลงโค้ดใหม่แต่ละชุด
  2. Code Detective
    ผู้ที่ดูการกระทำหลังจากรวมเข้าด้วยกันแล้ว โดยทั่วไปแล้วบุคคลเหล่านี้คือบุคคลที่ย้อนกลับไปในประวัติศาสตร์เพื่อพยายามทำความเข้าใจว่าเหตุใดจึงมีการเพิ่มบางอย่างหรือเมื่อมีการแนะนำข้อผิดพลาด หากไม่มีชื่อที่ดีกว่านี้ ฉันจะเรียกคนเหล่านี้ว่า "นักสืบรหัส" เพื่อแยกแยะพวกเขาจากคนด้านบน

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

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

การตัดสินใจ การตัดสินใจ

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

หากไม่มีบริบทเพิ่มเติม จะต้องทำการตัดสินใจต่อไปนี้เมื่อดูโค้ด "เพิ่ม" บรรทัดเดียว:

  1. นี่เป็นโค้ดบรรทัดใหม่ทั้งหมดหรือไม่
  2. ถ้าไม่ใช่โค้ดบรรทัดใหม่ แสดงว่าโค้ดบรรทัดเดิมเพิ่งย้ายมาจากที่อื่นใช่หรือไม่
  3. หากไม่ใช่บรรทัดใหม่ของโค้ดและไม่ได้ถูกย้าย จะเป็นการดัดแปลงเพียงเล็กน้อยของบรรทัดที่มีอยู่ (เช่น การเปลี่ยนแปลงการจัดรูปแบบ) หรือเป็นการเปลี่ยนแปลงเชิงตรรกะที่ถูกต้องหรือไม่
  4. หากเป็นโค้ดบรรทัดใหม่ทั้งหมดหรือการแก้ไขที่นำไปสู่การเปลี่ยนแปลงเชิงตรรกะ ทำไมถึงทำอย่างนั้น ทำถูกต้องหรือไม่? สามารถทำให้ง่ายขึ้นหรือปรับปรุงได้หรือไม่?

เราสามารถเห็นกระบวนการที่คล้ายกันสำหรับแต่ละบรรทัดของรหัส "ลบ":

  1. บรรทัดนี้ถูกลบออกทั้งหมดหรือไม่?
  2. หากไม่ถูกลบออกทั้งหมด จะถูกย้ายหรือแก้ไขหรือไม่?
  3. หากไม่ ได้ ถูกลบออกทั้งหมดและไม่ใช่เพียงแค่ถูกย้าย เป็นผลมาจากการปรับเปลี่ยนเล็กน้อย (เช่น: การจัดรูปแบบ) หรือเป็นผลมาจากการเปลี่ยนแปลงเชิงตรรกะ
  4. หากเป็นการดัดแปลงเชิงตรรกะจริง ๆ แล้วเหตุใดจึงถูกแก้ไข ดำเนินการถูกต้องหรือไม่?
  5. หากบรรทัดถูกลบออกทั้งหมด ทำไมถึงไม่ต้องการอีกต่อไป

ในที่สุดสิ่งนี้ทำให้เรากลับมาสู่ความเหนื่อยล้าในการตัดสินใจ:

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

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

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

1. วางการแก้ไขเล็กน้อยในการกระทำของตนเอง

สิ่งที่ง่ายที่สุดและสำคัญที่สุดที่ต้องทำคือแยกการแก้ไขเล็กน้อยออกเป็นการกระทำของตนเอง ตัวอย่างบางส่วน ได้แก่ :

  • การเปลี่ยนแปลงการจัดรูปแบบโค้ด
  • ฟังก์ชั่น / ตัวแปร / เปลี่ยนชื่อคลาส
  • การจัดลำดับใหม่ของฟังก์ชัน / ตัวแปร / การนำเข้าภายในคลาส
  • การลบรหัสที่ไม่ได้ใช้
  • การย้ายตำแหน่งไฟล์

พิจารณาการกระทำต่อไปนี้ผสมการเปลี่ยนแปลงเล็กน้อยกับการเปลี่ยนแปลงเล็กน้อย:

ข้อความยืนยัน: “อัพเดทรายการผลไม้ที่ถูกต้อง”

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

ข้อความยืนยัน: “อัปเดตการจัดรูปแบบรายการผลไม้ที่ถูกต้อง”

ส่งข้อความ: “เพิ่มวันที่ในรายการผลไม้ที่ถูกต้อง”

โดยพื้นฐานแล้วการคอมมิต "การจัดรูปแบบเท่านั้น" นั้นสามารถถูกละเว้นได้และสามารถค้นพบโค้ดเพิ่มเติมได้ทันทีในทันที

2. วางโค้ดรีแฟคเตอร์ในการคอมมิตของตนเอง

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

ตัวอย่างเช่น คุณจะมองเห็นข้อผิดพลาดตรงนี้ได้เร็วเพียงใด

ข้อความคอมมิต: "อัปเดตตรรกะของทิป"

แล้วตอนนี้กับ refactor ที่แยกออกมาล่ะ?

ข้อความยืนยัน: “แยกอัตราทิปเริ่มต้น”

ส่งข้อความ: “อนุญาตสำหรับอัตราค่าทิปที่กำหนดเอง”

3. วางการแก้ไขข้อผิดพลาดในการกระทำของตนเอง

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

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

4. ทำการเปลี่ยนแปลงเชิงตรรกะแยกกันในการกระทำของตนเอง

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

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

5. รวมการเปลี่ยนแปลงการตรวจสอบใด ๆ เข้ากับความมุ่งมั่นที่พวกเขาเป็นเจ้าของ

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

- <Initial commits>
- Respond to review feedback
- Work
- More work
- Addressing more review feedback

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

พิจารณาการเปลี่ยนแปลงเริ่มต้นนี้ตามด้วย "งาน" หลายอย่าง:

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

6. รีเบส รีเบส รีเบส!

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

  1. รวมสาขาหลักเข้ากับสาขาคุณลักษณะ สิ่งนี้จะสร้าง "การผสานรวม" ซึ่งรวมการเปลี่ยนแปลงรหัสทั้งหมดที่จำเป็นเพื่อแก้ไขข้อขัดแย้ง หากสาขาฟีเจอร์นั้นเก่าเป็นพิเศษ การคอมมิตประเภทนี้อาจมีจำนวนมาก
  2. Rebase สาขาฟีเจอร์กับสาขาหลัก ผลิตภัณฑ์สุดท้ายที่นี่คือชุดคอมมิชชันใหม่ที่ทำหน้าที่ราวกับว่าเพิ่งสร้างขึ้นตามสาขาหลักที่อัปเดต ข้อขัดแย้งใด ๆ จะต้องได้รับการจัดการโดยเป็นส่วนหนึ่งของกระบวนการรีเบส แต่หลักฐานทั้งหมดของรหัสเวอร์ชันดั้งเดิมจะหายไป

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

พิจารณาประวัติโครงการต่อไปนี้ที่ใช้การผสานระหว่างสาขา:

การใช้กลยุทธ์การควบรวมกิจการ แทนที่จะใช้การรีเบส อาจส่งผลให้เกิดประวัติศาสตร์ที่ซับซ้อน

เปรียบเทียบสิ่งนี้กับโครงการที่ rebases การเปลี่ยนแปลงทั้งหมดและห้ามการรวมคอมมิตแม้ในขณะที่รวมคุณสมบัติเข้ากับสาขาหลัก :

โปรเจ็กต์ที่ใช้การรีเบสและห้ามการคอมมิตแบบผสานทั้งหมดจะปรากฏเป็นเส้นเวลาเชิงเส้นเส้นเดียว

ในอดีต ความสัมพันธ์ระหว่างการเปลี่ยนแปลงจะต้องมีการวางแผน ไตร่ตรอง และถอดรหัส; ในช่วงหลังคุณเพียงแค่ไหลไปข้างหน้าและย้อนกลับในเวลา

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

ข้อโต้แย้ง

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

“การกังวลเกี่ยวกับโครงสร้างคอมมิชชันมากทำให้การพัฒนาช้าลง”

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

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

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

“ไม่ใช่ไซต์โฮสติ้ง git ทุกไซต์ที่อนุญาตให้ดึงคำขอที่มีการคอมมิตหลายรายการ”

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

“การกระทำเพียงครั้งเดียวทำให้มั่นใจได้ว่าการเปลี่ยนแปลงทั้งหมดรวบรวมและผ่านการทดสอบ”

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

“การกระทำเพียงครั้งเดียวให้บริบทมากที่สุดสำหรับการเปลี่ยนแปลงทั้งหมด”

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

#74 ที่นี่คือลิงก์กลับไปที่ Pull Request ที่สร้างการคอมมิตนี้ ทำให้สามารถดูการคอมมิตที่เกี่ยวข้องจาก PR เดียวกันได้

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

ความคิดสุดท้าย

ฉันหวังว่าจะทำให้คุณมั่นใจว่าการแยกการเปลี่ยนแปลงรหัสออกเป็นการกระทำที่แตกต่างกันหลายประเภทมีประโยชน์สำหรับทุกคนในกระบวนการพัฒนา:

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

Brian ทำงานที่Livefrontซึ่งเขาพยายามสร้างประวัติศาสตร์ (git) เพิ่มเติมอีกเล็กน้อย