มนุษย์ได้ต่อสู้กับศิลปะและวิทยาศาสตร์ของการเขียนโปรแกรมคอมพิวเตอร์มาประมาณครึ่งศตวรรษแล้ว เมื่อเทียบกับศิลปะและวิทยาศาสตร์ส่วนใหญ่แล้ววิทยาการคอมพิวเตอร์ยังคงเป็นเพียงเด็กวัยเตาะแตะเดินชนกำแพงสะดุดเท้าตัวเองและโยนอาหารลงบนโต๊ะเป็นครั้งคราว
อันเป็นผลมาจากความเยาว์วัยฉันไม่เชื่อว่าเรามีความเห็นพ้องต้องกันว่าคำจำกัดความที่เหมาะสมของ“ รหัสที่ดี” คืออะไรเนื่องจากคำจำกัดความนั้นยังคงพัฒนาต่อไป บางคนจะบอกว่า“ รหัสที่ดี” คือรหัสที่ครอบคลุมการทดสอบ 100% คนอื่น ๆ จะบอกว่ามันเร็วมากและมีประสิทธิภาพที่ยอดเยี่ยมและจะทำงานได้อย่างน่าพอใจในฮาร์ดแวร์อายุ 10 ปี
แม้ว่าสิ่งเหล่านี้จะเป็นเป้าหมายที่น่ายกย่องสำหรับนักพัฒนาซอฟต์แวร์ แต่ฉันก็พยายามที่จะโยนเป้าหมายอื่นเข้าไปในส่วนผสมนั่นคือการบำรุงรักษา โดยเฉพาะอย่างยิ่ง“ รหัสที่ดี” คือรหัสที่องค์กรสามารถดูแลรักษาได้ง่ายและพร้อมใช้งาน (ไม่ใช่แค่ผู้เขียนเท่านั้น!) และจะอยู่ได้นานกว่าการวิ่งที่เขียนไว้เท่านั้นต่อไปนี้เป็นบางสิ่งที่ฉันค้นพบใน อาชีพเป็นวิศวกรใน บริษัท ขนาดใหญ่และขนาดเล็กในสหรัฐอเมริกาและต่างประเทศซึ่งดูเหมือนจะมีความสัมพันธ์กับซอฟต์แวร์ที่ 'ดี' ที่บำรุงรักษาได้
ฉันอยู่ไกลจากคนแรกที่เขียนว่าผู้ชมหลักสำหรับโค้ดของคุณไม่ใช่คอมไพเลอร์ / คอมพิวเตอร์ แต่ต่อไปใครจะต้องอ่านทำความเข้าใจดูแลรักษาและปรับปรุงโค้ด (ซึ่งไม่จำเป็นต้องเป็นคุณในหกเดือนนับจากนี้ ). วิศวกรทุกคนที่คุ้มค่าที่จะจ่ายสามารถสร้างรหัสที่ 'ใช้งานได้'; สิ่งที่สร้างความแตกต่างให้กับวิศวกรที่ยอดเยี่ยมคือพวกเขาสามารถเขียนโค้ดบำรุงรักษาได้อย่างมีประสิทธิภาพซึ่งสนับสนุนธุรกิจในระยะยาวและมีทักษะในการแก้ปัญหาอย่างเรียบง่ายและชัดเจนและบำรุงรักษาได้
ในภาษาโปรแกรมใด ๆ คุณสามารถเขียนโค้ดที่ดีหรือโค้ดที่ไม่ถูกต้องได้ สมมติว่าเราตัดสินภาษาโปรแกรมด้วยวิธีที่ช่วยอำนวยความสะดวกในการเขียนโค้ดที่ดี (อย่างน้อยก็ควรเป็นหนึ่งในเกณฑ์อันดับต้น ๆ อยู่ดี) ภาษาโปรแกรมใด ๆ อาจเป็น 'ดี' หรือ 'ไม่ดี' ขึ้นอยู่กับวิธีการใช้ (หรือใช้ในทางที่ผิด ).
ตัวอย่างของภาษาที่หลายคนถือว่า 'สะอาด' และอ่านได้คือ Python ภาษาเองบังคับใช้ระเบียบวินัยพื้นที่สีขาวในระดับหนึ่งและ API ในตัวมีมากมายและค่อนข้างสอดคล้องกัน กล่าวได้ว่าเป็นไปได้ที่จะสร้างสัตว์ประหลาดที่ไม่สามารถบรรยายได้ ตัวอย่างเช่นเราสามารถกำหนดคลาสและกำหนด / กำหนดใหม่ / ไม่กำหนดวิธีการใด ๆ และทุกวิธีในคลาสนั้นในระหว่างรันไทม์ (มักเรียกว่าการปะลิง) เทคนิคนี้นำไปสู่ API ที่ไม่สอดคล้องกันอย่างดีที่สุดและที่แย่ที่สุดคือเป็นไปไม่ได้ที่จะดีบักมอนสเตอร์ อาจมีคนคิดว่า 'แน่นอน แต่ไม่มีใครทำอย่างนั้น!' น่าเสียดายที่ใช้งานได้และใช้เวลาเรียกดูไม่นาน pypi ก่อนที่คุณจะเข้าสู่ไลบรารีจำนวนมาก (และเป็นที่นิยม!) ซึ่ง (ab) ใช้การปะลิงอย่างกว้างขวางเป็นแกนหลักของ API ฉันเพิ่งใช้ไลบรารีเครือข่ายที่มีการเปลี่ยนแปลง API ทั้งหมดขึ้นอยู่กับสถานะเครือข่ายของออบเจ็กต์ ลองนึกภาพเช่นเรียก client.connect()
และบางครั้งก็ได้รับ MethodDoesNotExist
แทนข้อผิดพลาด HostNotFound
หรือ NetworkUnavailable
.
โค้ดที่ดีนั้นอ่านและเข้าใจได้ง่ายโดยบางส่วนและทั้งหมดโดยผู้อื่น (เช่นเดียวกับผู้เขียนในอนาคตพยายามหลีกเลี่ยง “ ฉันเขียนอย่างนั้นจริงๆเหรอ” ดาวน์ซินโดรม).
โดย“ บางส่วน” ฉันหมายความว่าถ้าฉันเปิดโมดูลหรือฟังก์ชันบางอย่างในโค้ดฉันควรจะเข้าใจว่ามันทำอะไรได้บ้างโดยไม่ต้องอ่านโค้ดเบสที่เหลือทั้งหมด ควรใช้งานง่ายและจัดทำเอกสารด้วยตนเองให้มากที่สุด
โค้ดที่อ้างอิงรายละเอียดนาทีที่ส่งผลต่อพฤติกรรมจากส่วนอื่น ๆ (ที่ดูเหมือนไม่เกี่ยวข้อง) ของโค้ดเบสอยู่ตลอดเวลาก็เหมือนกับการอ่านหนังสือที่คุณต้องอ้างอิงเชิงอรรถหรือภาคผนวกท้ายทุกประโยค คุณจะไม่ผ่านหน้าแรก!
ความคิดอื่น ๆ เกี่ยวกับการอ่าน 'ท้องถิ่น':
ดี ห่อหุ้ม โค้ดมีแนวโน้มที่จะอ่านได้ง่ายขึ้น แยกความกังวล ในทุกระดับ
ชื่อมีความสำคัญ เปิดใช้งาน คิดเร็วและช้า ระบบ 2 วิธีที่สมองสร้างความคิดและใส่ความคิดที่รอบคอบและระมัดระวังลงในชื่อตัวแปรและวิธีการ ไม่กี่วินาทีพิเศษสามารถจ่ายเงินปันผลจำนวนมากได้ ตัวแปรที่มีชื่อดีสามารถทำให้โค้ดใช้งานง่ายขึ้นมากในขณะที่ตัวแปรที่มีชื่อไม่ดีอาจนำไปสู่การปลอมแปลงและความสับสน
ความฉลาดเป็นศัตรู เมื่อใช้เทคนิคแฟนซีกระบวนทัศน์หรือการดำเนินการ (เช่นความเข้าใจในรายการหรือตัวดำเนินการที่เกี่ยวข้อง) โปรดใช้ความระมัดระวังในการใช้ในลักษณะที่ทำให้โค้ดของคุณ มากกว่า อ่านได้ไม่ใช่แค่สั้นกว่า
ความสม่ำเสมอเป็นสิ่งที่ดี ความสม่ำเสมอในรูปแบบทั้งในแง่ของวิธีการจัดฟัน แต่ในแง่ของการใช้งานช่วยเพิ่มความสามารถในการอ่านอย่างมาก
การแยกความกังวล . โครงการหนึ่ง ๆ จัดการสมมติฐานที่สำคัญในท้องถิ่นจำนวนมากมายนับไม่ถ้วน ณ จุดต่างๆในโค้ดเบส เปิดเผยแต่ละส่วนของ codebase ให้น้อยที่สุดเท่าที่จะเป็นไปได้ สมมติว่าคุณมีระบบการจัดการบุคคลที่บางครั้งวัตถุบุคคลอาจมีนามสกุลว่าง สำหรับใครบางคนที่เขียนโค้ดในหน้าที่แสดงวัตถุบุคคลนั่นอาจเป็นเรื่องที่น่าอึดอัดใจจริงๆ! และถ้าคุณไม่เก็บคู่มือ“ ข้อสันนิษฐานที่น่าอึดอัดและไม่ชัดเจน codebase ของเรามี” (ฉันรู้ว่าฉันไม่รู้) โปรแกรมเมอร์หน้าแสดงของคุณจะไม่ทราบว่านามสกุลอาจเป็นโมฆะและอาจจะเขียนโค้ดด้วยตัวชี้ค่าว่าง ข้อยกเว้นในนั้นเมื่อกรณีว่างของนามสกุลปรากฏขึ้น แทนที่จะจัดการกรณีเหล่านี้ด้วย API และสัญญาที่คิดมาเป็นอย่างดีซึ่งส่วนต่างๆของ codebase ของคุณใช้เพื่อโต้ตอบกัน
รัฐคือศัตรู ทำไม? เนื่องจากเป็นส่วนเดียวที่ซับซ้อนที่สุดของแอปพลิเคชันใด ๆ และจำเป็นต้องได้รับการจัดการอย่างรอบคอบและรอบคอบ ปัญหาที่พบบ่อย ได้แก่ ความไม่สอดคล้องกันของฐานข้อมูลการอัปเดต UI บางส่วนซึ่งข้อมูลใหม่ไม่ได้แสดงให้เห็นในทุกที่การดำเนินการที่ไม่ได้รับคำสั่งหรือเพียงแค่นึกถึงโค้ดที่ซับซ้อนซึ่งทำให้มึนงงด้วยคำสั่ง if และกิ่งก้านทุกที่ซึ่งทำให้อ่านยากและยากต่อการดูแลรักษาโค้ด การวางสถานะบนฐานเพื่อให้ได้รับการปฏิบัติด้วยความระมัดระวังเป็นอย่างยิ่งและมีความสอดคล้องและรอบคอบอย่างยิ่งในเรื่องการเข้าถึงและแก้ไขสถานะทำให้โค้ดเบสของคุณง่ายขึ้นอย่างมาก บางภาษา (ตัวอย่างเช่น Haskell) บังคับใช้ในระดับโปรแกรมและไวยากรณ์ คุณจะประหลาดใจว่าความชัดเจนของ codebase ของคุณสามารถปรับปรุงได้มากเพียงใดหากคุณมีไลบรารี บริสุทธิ์ ฟังก์ชันที่ไม่มีการเข้าถึงสถานะภายนอกและพื้นที่ผิวขนาดเล็กของรหัสสถานะซึ่งอ้างอิงถึงฟังก์ชันภายนอกที่บริสุทธิ์
ก่อนที่จะสร้างวงล้อขึ้นมาใหม่ให้คิดว่าคุณกำลังพยายามแก้ไขปัญหาทั่วไปเพียงใดหรือฟังก์ชันที่คุณกำลังพยายามดำเนินการอยู่ บางคนอาจใช้วิธีแก้ปัญหาที่คุณสามารถใช้ประโยชน์ได้แล้ว ใช้เวลาในการพิจารณาและค้นคว้าทางเลือกดังกล่าวหากเหมาะสมและมีอยู่
กล่าวได้ว่าการโต้แย้งโต้แย้งที่สมเหตุสมผลอย่างสมบูรณ์คือการอ้างอิงไม่ได้มาเพื่อ“ ฟรี” โดยไม่มีข้อเสียใด ๆ ด้วยการใช้ไลบรารีของบุคคลที่สามหรือโอเพนซอร์สที่เพิ่มฟังก์ชันการทำงานที่น่าสนใจคุณกำลังให้คำมั่นสัญญาและขึ้นอยู่กับไลบรารีนั้น นั่นคือความมุ่งมั่นที่ยิ่งใหญ่ หากเป็นไลบรารีขนาดใหญ่และคุณต้องการฟังก์ชันเพียงเล็กน้อยคุณต้องการภาระในการอัปเดตไลบรารีทั้งหมดหรือไม่หากคุณอัปเกรดเป็น Python 3.x และยิ่งไปกว่านั้นหากคุณพบข้อบกพร่องหรือต้องการปรับปรุงฟังก์ชันการทำงานคุณอาจต้องพึ่งพาผู้เขียน (หรือผู้ขาย) ในการจัดหาการแก้ไขหรือการปรับปรุงหรือหากเป็นโอเพ่นซอร์สให้พบว่าตัวเองอยู่ในตำแหน่งของการสำรวจ ( อาจมีนัยสำคัญ) codebase คุณไม่คุ้นเคยกับการพยายามแก้ไขหรือปรับเปลี่ยนฟังก์ชันการทำงานที่คลุมเครือเล็กน้อย
แน่นอนว่ายิ่งคุณใช้รหัสได้ดีเท่าใดก็ยิ่งมีโอกาสน้อยที่คุณจะต้องเสียเวลาไปกับการบำรุงรักษา สิ่งที่สำคัญที่สุดก็คือคุณควรทำวิจัยด้วยตัวเองและทำการประเมินด้วยตนเองว่าจะรวมเทคโนโลยีภายนอกหรือไม่และการบำรุงรักษาเทคโนโลยีนั้น ๆ จะเพิ่มลงในสแต็กของคุณหรือไม่
ด้านล่างนี้คือตัวอย่างทั่วไปบางส่วนของสิ่งที่คุณไม่ควรนำมาใช้ใหม่ในยุคใหม่ในโครงการของคุณ (เว้นแต่สิ่งเหล่านี้จะเป็นโครงการของคุณ)
คิดออกว่าอะไร หมวก ที่คุณต้องการสำหรับโครงการของคุณจากนั้นเลือกฐานข้อมูลที่มีคุณสมบัติที่เหมาะสม ฐานข้อมูลไม่ได้หมายถึง MySQL อีกต่อไปคุณสามารถเลือกจาก:
ในสถานการณ์ส่วนใหญ่คุณไม่ควรเขียนแบบสอบถามดิบไปยังฐานข้อมูลใดก็ตามที่คุณเลือกใช้ มีความเป็นไปได้สูงที่จะมีไลบรารีสำหรับนั่งระหว่างฐานข้อมูลและรหัสแอปพลิเคชันของคุณซึ่งแยกข้อกังวลในการจัดการเซสชันฐานข้อมูลพร้อมกันและรายละเอียดของสคีมาจากโค้ดหลักของคุณ อย่างน้อยที่สุดคุณไม่ควรมีแบบสอบถามดิบหรือ SQL อินไลน์ตรงกลางรหัสแอปพลิเคชันของคุณ แทนที่จะรวมไว้ในฟังก์ชันและรวมฟังก์ชันทั้งหมดไว้ในไฟล์ที่เรียกว่าสิ่งที่ชัดเจนจริงๆ (เช่น“ queries.py”) บรรทัดเช่น users = load_users()
เช่นอ่านง่ายกว่า users = db.query(“SELECT username, foo, bar from users LIMIT 10 ORDER BY ID”)
การรวมศูนย์ประเภทนี้ยังช่วยให้มีรูปแบบที่สอดคล้องกันในการสืบค้นของคุณง่ายขึ้นมากและ จำกัด จำนวนสถานที่ที่จะไปเพื่อเปลี่ยนแปลงการสืบค้นหากสคีมาเปลี่ยนแปลง
มีโมเดลที่ดีมากมายสำหรับการออกแบบโปรแกรม ผับ / ย่อย , นักแสดง , MVC ฯลฯ เลือกสิ่งที่คุณชอบที่สุดและยึดติดกับมัน ตรรกะที่แตกต่างกันที่เกี่ยวข้องกับข้อมูลประเภทต่างๆควรแยกออกจากกันทางกายภาพใน codebase (อีกครั้งการแยกแนวคิดเกี่ยวกับความกังวลนี้และการลดภาระทางปัญญาในผู้อ่านในอนาคต) โค้ดที่อัปเดต UI ของคุณควรแตกต่างจากโค้ดที่คำนวณสิ่งที่จะเข้าสู่ UI เช่น
หากคอมไพเลอร์สามารถตรวจจับข้อผิดพลาดทางตรรกะในโค้ดของคุณและป้องกันพฤติกรรมที่ไม่ดีข้อบกพร่องหรือข้อขัดข้องโดยสิ้นเชิงเราควรใช้ประโยชน์จากสิ่งนั้นอย่างยิ่ง แน่นอนว่าบางภาษามีคอมไพเลอร์ที่ทำให้ง่ายกว่าภาษาอื่น ๆ ตัวอย่างเช่น Haskell มีชื่อเสียงที่เข้มงวด คอมไพเลอร์ ซึ่งส่งผลให้โปรแกรมเมอร์ใช้ความพยายามส่วนใหญ่เพียงแค่รับโค้ดมาคอมไพล์ เมื่อรวบรวมแล้ว 'มันก็ใช้ได้' สำหรับพวกคุณที่ไม่เคยเขียนด้วยภาษาที่ใช้งานได้อย่างรุนแรงสิ่งนี้อาจดูเหมือนไร้สาระหรือเป็นไปไม่ได้ แต่ ไม่ ใช้เวลา ของฉัน คำ สำหรับมัน. อย่างจริงจังคลิกที่ลิงก์เหล่านี้เป็นไปได้อย่างแน่นอนที่จะอยู่ในโลกโดยไม่มีข้อผิดพลาดรันไทม์ และมันก็มีมนต์ขลังจริงๆ
เป็นที่ยอมรับไม่ใช่ทุกภาษาที่มีคอมไพเลอร์หรือไวยากรณ์ที่ยืมตัวเองไปใช้กับการตรวจสอบเวลาคอมไพล์มาก (หรือในบางกรณี!) สำหรับผู้ที่ยังไม่มีให้ใช้เวลาสักครู่เพื่อศึกษาว่าการตรวจสอบความเข้มงวดที่เป็นทางเลือกใดที่คุณสามารถเปิดใช้งานได้ในโครงการของคุณและประเมินว่าเหมาะสมกับคุณหรือไม่ รายการสั้น ๆ ที่ไม่ครอบคลุมของคำศัพท์ทั่วไปที่ฉันใช้เมื่อเร็ว ๆ นี้สำหรับภาษาที่มีช่วงเวลาที่ผ่อนปรน ได้แก่ :
นี่ไม่ใช่รายการบัญญัติที่ครบถ้วนสมบูรณ์หรือสมบูรณ์สำหรับการสร้างรหัสที่“ ดี” (เช่นบำรุงรักษาได้ง่าย) ที่กล่าวว่าหากทุก ๆ โค้ดเบสที่ฉันต้องรับในอนาคตทำตามแม้กระทั่งครึ่งหนึ่งของแนวคิดในรายการนี้ฉันจะมีผมหงอกน้อยลงมากและอาจจะเพิ่มอีกห้าปีในตอนท้ายของชีวิตของฉัน และฉันจะพบว่างานสนุกขึ้นและเครียดน้อยลงอย่างแน่นอน