ทำไมคอมเมนต์แบบ “Why Not” จึงจำเป็น
(buttondown.com)- คอมเมนต์สามารถใช้ ภาษามนุษย์ ที่สื่อความหมายได้มากกว่าตัวระบุ จึงเหมาะกับการบันทึกทางเลือกที่ไม่มีในโค้ดและทางเลือกที่ตัดสินใจไม่ใช้
- วลี “comment the why, not the what” เป็นแนวทางที่พยายามใส่ข้อมูลลงในตัวระบุให้ได้มากที่สุด แต่ช่วงหลังมีแนวโน้มจะย้ายแม้กระทั่งเหตุผลไปไว้ในชื่อฟังก์ชันยาว ๆ หรือชื่อเทสต์
- ในการ build epub ของ
Logic for Programmersมีการใช้ implementation ที่ช้า โดยแทนที่สัญลักษณ์คณิตศาสตร์ 16 ตัวแบบไล่ทีละสตริง แต่ตอนนี้มีสตริงคณิตศาสตร์อยู่แค่ 25 รายการ จึง เร็วพอ - คอมเมนต์แบบนี้จะช่วยบอกตำแหน่งที่ควรแก้ในอนาคต หากภายหลังจำนวนสตริงคณิตศาสตร์เพิ่มเป็นหลายร้อยรายการจนกลายเป็นคอขวดของการ build และยังบันทึกไว้ว่าโค้ดที่ช้านั้นเป็น trade-off ที่ตั้งใจเลือก
- ชื่อฟังก์ชันหรือเทสต์เป็นสิ่งที่ผูกกับสิ่งที่โค้ดทำจริง จึงยากจะทำให้เป็น self-documenting สำหรับ ข้อมูลเชิงปฏิเสธ ที่ว่ามีทางเลือกใดที่ไม่ได้เลือก หรือมีอะไรที่โค้ดไม่ได้ทำ
ข้อมูลที่คอมเมนต์เก็บได้ง่ายกว่าโค้ด
- โค้ดเป็นภาษาสำหรับเครื่องที่มีโครงสร้าง ส่วนคอมเมนต์เขียนด้วย ภาษามนุษย์ ที่แสดงความหมายได้หลากหลายกว่า
- “comment the why, not the what” อาจถูกตีความได้ว่าให้ใส่ข้อมูลลงในตัวระบุให้มากที่สุดเท่าที่ทำได้
- ตัวระบุคล้ายภาษามนุษย์แบบจำกัดที่ฝังอยู่ในโค้ด แม้จะใส่ “what” ได้ไม่ครบทุกอย่าง แต่ในหลายกรณีก็ทำได้มากพอ
- ช่วงหลังมีคนเห็นมากขึ้นว่าแม้แต่ “why” ก็ไม่จำเป็นต้องอยู่ในคอมเมนต์ แต่อาจใส่ไว้ในชื่อฟังก์ชันยาว ๆ หรือชื่อ test case ได้
- codebase ที่เป็น self-documenting มักเพิ่มการอธิบายด้วยการ เพิ่มตัวระบุ
- มีข้อยกเว้นอยู่บ้าง เช่น กรณีที่เปลี่ยนคอมเมนต์ให้เป็น logging เพื่อให้โค้ด self-documenting มากขึ้น
คอมเมนต์แบบ “Why Not” จัดการกับอะไร
- ข้อมูลที่แสดงผ่านโค้ดได้ยากคือ ข้อมูลเชิงปฏิเสธ
- ข้อมูลเชิงปฏิเสธช่วยดึงความสนใจไปที่สิ่งที่ไม่มีอยู่ในระบบ หรือเหตุผลว่าทำไมจึงไม่ได้เลือกทางเลือกบางอย่าง
- “why not” ไม่ได้อธิบายว่าโค้ดทำอะไร แต่เก็บบันทึกว่ามีทางเลือกใดที่โค้ดไม่ได้ทำ และเพราะอะไร
กรณีการแทนที่สัญลักษณ์คณิตศาสตร์ใน epub
- ในการ build epub ของ
Logic for Programmersด้วยเหตุผลทางเทคนิค สัญลักษณ์คณิตศาสตร์อย่าง\forallจึงไม่ถูกแปลงเป็นสัญลักษณ์อย่าง∀ - เพื่อแก้ปัญหานี้ จึงเขียนสคริปต์ที่แทนที่ token ภายในสตริงคณิตศาสตร์ด้วยสัญลักษณ์ยูนิโค้ดที่ตรงกันโดยตรง
- implementation ที่ง่ายที่สุดคือเรียก
string = string.replace(old, new)สำหรับ สัญลักษณ์คณิตศาสตร์ 16 ตัว ที่ต้องใช้แต่ละตัว - วิธีนี้ไม่มีประสิทธิภาพเพราะต้องวนผ่านแต่ละสตริง 16 รอบ แต่ถ้าจะทำให้ครบทั้ง 16 การแทนที่ในรอบเดียว โค้ดก็จะซับซ้อนขึ้น
- ใจความของคอมเมนต์ที่ทิ้งไว้มีดังนี้
- แต่ละสตริงถูกวนผ่าน 16 รอบ
- ตอนนี้ในหนังสือมีสตริงคณิตศาสตร์แค่ 25 รายการ และส่วนใหญ่ยาวไม่ถึง 5 ตัวอักษร
- ดังนั้นจึงยังเร็วพออยู่ดี
- คอมเมนต์นี้ไม่ได้อธิบายแค่ว่า “ทำไมจึงใช้โค้ดที่ช้า” แต่ยังอธิบายด้วยว่า “ทำไมจึงไม่ใช้โค้ดที่เร็วกว่า”
ป้ายบอกทางสำหรับผู้อ่านในอนาคต
- ต่อให้โค้ดที่ช้ายังไม่เป็นปัญหาในตอนนี้ วันหนึ่งมันก็อาจกลายเป็นปัญหาได้
- หาก
Logic for Programmersเวอร์ชันในอนาคตมีสตริงคณิตศาสตร์เพิ่มเป็นหลายร้อยรายการ ขั้นตอน build นี้อาจกลายเป็นคอขวดของทั้งกระบวนการ build - ถ้าทิ้งป้ายบอกทางไว้ตั้งแต่ตอนนี้ ภายหลังก็จะรู้ได้ทันทีว่าควรไปแก้ตรงไหน
- แม้โค้ดจะยังทำงานได้โดยไม่มีปัญหาต่อไป คอมเมนต์ก็ยังเก็บรักษาความจริงที่ว่า ผู้เขียนรู้ว่ามี trade-off นี้อยู่
- เมื่อกลับมาเปิด
epub_math_fixer.pyอีกครั้งในอีก 2 ปีข้างหน้า ก็ไม่ต้องเสียเวลาสืบใหม่ว่าโค้ดที่ช้านั้นเกิดจากความไม่ชำนาญ เวลาไม่พอ หรือความผิดพลาดกันแน่ - คอมเมนต์เชิงปฏิเสธทิ้งร่องรอยไว้ว่าผู้เขียนรู้ถึง implementation ที่ช้า พิจารณาทางเลือกอื่นแล้ว และตัดสินใจว่าจะไม่ optimize มัน
ทำไมจึงแทนด้วยชื่อฟังก์ชันและเทสต์ได้ยาก
- ชื่อฟังก์ชันอย่าง
RunFewerTimesSlowerAndSimplerAlgorithmAfterConsideringTradeOffsยาวเกินไป และก็ยังอธิบาย trade-off ที่แท้จริงได้ไม่เพียงพอ - ถ้าภายหลังมีการ optimize โค้ด ชื่อนี้อาจต้องถูกแก้ในหลายจุด
- ปัญหาที่ใหญ่กว่าคือชื่อแบบนี้ไม่ได้บอกเลยว่าฟังก์ชันนั้นทำ อะไรจริง ๆ จึงกลับทำให้ความเป็น self-documenting อ่อนลง
- ตัวระบุอย่างชื่อฟังก์ชันและชื่อตัวแปรรองรับข้อมูลได้เพียงหนึ่งวลีเท่านั้น
- จึงยากที่จะใส่ทั้ง “สิ่งที่ฟังก์ชันทำ” และ “trade-off ที่ฟังก์ชันยอมรับ” ไว้ในตัวระบุเดียวกันพร้อมกัน
ข้อมูลเชิงปฏิเสธที่เก็บไว้ด้วยเทสต์ก็ทำได้ยาก
- เราอาจสร้างเทสต์ที่ grep หา math block ในหนังสือแล้วให้ล้มเหลวถ้าจำนวนเกิน 80 ได้
- แต่เทสต์แบบนั้นไม่ได้ทดสอบ
EpubMathFixerโดยตรง - ภายในฟังก์ชันเองก็ไม่มีจุดใดที่เทสต์ดังกล่าวจะไป hook ได้
- การทำให้โค้ด self-documenting คือการให้คำอธิบายแนบไปกับโค้ดที่เขียนอยู่ เพื่ออธิบายสิ่งที่โค้ดนั้นทำ
- แต่ข้อมูลเชิงปฏิเสธพูดถึงสิ่งที่โค้ดไม่ได้ทำ จึงไม่เข้ากับแนวทาง self-documenting โดยพื้นฐาน
คำถามที่กว้างกว่า
- คอมเมนต์แบบ “why not” อาจมองได้ว่าเป็นตัวอย่างหนึ่งของข้อมูลสวนทางข้อเท็จจริง (counterfactual)
- จึงยังมีคำถามต่อว่าองค์ประกอบเชิงนามธรรมของการสื่อสารระหว่างมนุษย์ โดยทั่วไปแล้วจะทำให้เป็น self-documenting ได้หรือไม่
- ข้อมูลอย่างอุปมา ความไม่แน่นอน หรือข้ออ้างเชิงจริยธรรม ก็ยังคงเป็นคำถามอยู่ว่าจะทำให้เป็น self-documenting ได้หรือไม่
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
จำมุกที่น่าจะเคยเห็นบน Twitter เมื่อหลายปีก่อนได้ว่า: “วิศวกรระดับจูเนียร์เขียนคอมเมนต์อธิบายว่าโค้ด ทำอะไร, วิศวกรระดับกลางเขียนคอมเมนต์อธิบายว่าโค้ด ทำไมถึงทำแบบนั้น, และวิศวกรระดับซีเนียร์เขียนคอมเมนต์อธิบายว่าทำไมโค้ดถึงไม่ได้ถูกเขียนเป็นอีกแบบหนึ่ง”
ในทางกลับกัน ถ้าตั้งชื่อฟังก์ชันและตัวแปรให้ชัดจนเข้าใจได้เอง ก็เคยเขียนฟังก์ชันค่อนข้างใหญ่โดยไม่ต้องมีคอมเมนต์เลยเหมือนกัน
เพราะงั้นฝั่งที่มีคอมเมนต์น้อยกว่าก็ดูเหมือนชนะ แต่เวลาเห็นโค้ดเบสที่แทบไม่มีคอมเมนต์ ก็ต้องลงไปดูเองถึงจะแยกได้ว่าเป็นผลงานชั้นครูที่ขัดเกลามาดี หรือเป็นโค้ดเปราะบางที่มือใหม่เขียน
มันอาจดูเป็นการแปะเทปแก้ปัญหาไปวัน ๆ แต่บางครั้งนั่นก็เป็นสิ่งที่ดีที่สุดเท่าที่จะทำได้จริง ๆ
ถ้าคิดว่าอีก 1 ปีข้างหน้ากลับมาดูแล้วจะเป็นประโยชน์กับตัวเอง ผมจะเขียนคอมเมนต์ไว้หมด โดยมากจะเป็นเรื่อง ทำไม และ ทำไมถึงทำไม่ได้ และถ้าโค้ดซับซ้อนก็จะเขียน “อะไร” แบบสั้น ๆ เพื่อช่วยมองเห็นลำดับการทำงาน
สิ่งที่ไม่มีประโยชน์คือคอมเมนต์ที่เขียนเพราะถูกบังคับ API สาธารณะควรมีเอกสารครบถ้วนอยู่แล้ว แต่บางองค์กรบังคับให้ใส่คอมเมนต์กับทุกฟังก์ชันแม้แต่ private function และจบลงด้วยการแค่พูดซ้ำชื่อฟังก์ชันเพราะจุดประสงค์มันชัดเจนเกินไป นี่ไม่ใช่แค่เสียเวลา แต่ยังทำให้คนชินชากับคอมเมนต์จนเรียนรู้นิสัยที่จะมองข้ามมัน
ผมยังไม่ชอบคอมเมนต์ไร้สาระที่เครื่องมือเติมให้ด้วย แบบที่ใส่
//forหรือ//tryให้ทุกลูปนี่แย่เป็นพิเศษทางที่ดีควรลบคอมเมนต์บังคับและคอมเมนต์ที่สร้างอัตโนมัติออก แล้วในธีมมืดก็ทำคอมเมนต์ให้เป็นสีนีออนสว่าง ๆ เพื่อให้เด่น ถ้ามีคอมเมนต์อยู่ นั่นควรหมายความว่ามันสำคัญ
ในสภาพแวดล้อมธุรกิจที่เดดไลน์บีบคั้นและต้องดูแลระบบเก่าขนาดใหญ่ บางทีก็ต้องทำเรื่องประหลาด ๆ และตอนนั้นคุณต้องอธิบายว่าทำไม
เหตุผลใหญ่ที่คนต่อต้านคอมเมนต์คือคอมเมนต์ก็กลายเป็นส่วนหนึ่งของโค้ดและต้องบำรุงรักษาเหมือนกัน แต่คนส่วนใหญ่อ่านคอมเมนต์ตอนที่ติดปัญหาเท่านั้น และตัวแก้ไขโค้ดก็มักทำให้คอมเมนต์เป็นสีเทาจาง ๆ จนมองไม่เห็นในเชิงจิตวิทยา เลยทำให้คอมเมนต์เก่าง่าย
เลยสงสัยว่าบริบทที่เขียนไว้ให้ “ตัวเราในอนาคต” มีประโยชน์ในโค้ดเบสร่วมที่นักพัฒนาหลายคนแตะต้องหรือไม่ หรือมันเป็นแนวทางที่เวิร์กก็ต่อเมื่อมีคนแตะโค้ดไม่กี่คน
สุดท้ายเลยเติม “=> yes!” ต่อท้ายคอมเมนต์เดิม และรู้สึกขอบคุณตัวเองในอดีตที่บันทึกความสงสัยนั้นไว้ ตอนทำงาน โดยเฉพาะเวลาซ่อมบั๊ก ผมมักทิ้งคอมเมนต์สั้น ๆ หนึ่งหรือสองบรรทัดพร้อม หมายเลขตั๋วงาน ไว้บนการเปลี่ยนแปลงที่ดูไม่ชัดเจน
รูปแบบคอมเมนต์ที่ผมชอบที่สุดเท่าที่เคยเขียนไว้ในโค้ด คือเทมเพลตนี้: “DEAR MAINTAINER: โค้ดนี้เป็นแบบนี้เพราะ [เหตุผล] ถ้าคุณพยายามจะ ‘แก้’ มันแล้วพบว่านั่นเป็นความผิดพลาดอันเลวร้าย กรุณาเพิ่มตัวนับ
total_hours_wasted_here = nเพื่อเตือนคนถัดไปด้วย”ผมไม่ใช่คนคิดต้นฉบับ แต่ก็เคยหยิบไปใช้อย่างซาบซึ้งอยู่ครั้งสองครั้ง และพอเห็นคอมมิตบรรทัดเดียวที่แค่เพิ่มตัวนับก็ตลกดี
ต่อมาวิศวกรที่ซีเนียร์กว่ารับช่วงโค้ดเบสไปแล้ว “แก้” ทุกอย่างให้เป็นแบบวนลูป พร้อมจะส่งอีเมลมาสั่งสอนว่าทำไม recursion ถึงไม่ดี แต่โค้ดของเขากลับไม่รองรับข้อกำหนดจริงทั้งหมด และสุดท้ายก็ต้องสร้างสิ่งที่ผมเคยทำด้วย recursion ขึ้นมาใหม่แทบทั้งหมด
หลังจากนั้นเขาก็ขอโทษสำหรับบางคำพูด แต่ถ้ามีคอมเมนต์แบบนี้แปะไว้ข้างบนตั้งแต่แรก งานทั้งหมดนั้นอาจหลีกเลี่ยงได้
เห็นด้วยว่าชื่อเรื่องกำกวม และนั่นแหละที่ทำให้ผมกดเข้ามาอ่าน โดยส่วนตัวผมยังชอบแนวทางที่ใช้คอมเมนต์น้อยโดยรวม แต่ คอมเมนต์เชิงอธิบาย ที่บทความพูดถึงมีคุณค่าชัดเจน เป็นเครื่องเตือนใจที่ดีให้บอกว่าทำไมถึงทำแบบนั้น และทำไมไม่ใช้วิธีอื่น
โดยเฉพาะกับโค้ดของตัวเองที่ต้องดูแลต่ออีก 5 ปี 10 ปี หรือ 15 ปี ไม่นานมานี้ผมรีวิวโค้ดใหม่ของเพื่อนร่วมงานแล้วคิดว่า “ทำไมทำแบบนี้นะ?” แต่พอดูขึ้นไป 10 บรรทัด ก็เจอเหตุผลที่ผมเองเขียนไว้เมื่อ 8 ปีก่อน เพื่อนคนนั้นแค่ทำตามกฎสำคัญของงานบำรุงรักษา นั่นคือทำให้มัน ดูเหมือนโค้ดเดิมที่มีอยู่
นี่เป็นเพียงกรณีพิเศษของหลักการที่กว้างกว่านั้น: ให้ใส่คอมเมนต์กับสิ่งที่ ชวนให้ประหลาดใจ เวลาอ่านโค้ด
ถ้าตอนเขียนโค้ดคุณถามตัวเองในใจตลอดว่า “เดี๋ยวกลับมาอ่านทีหลังจะเข้าใจโค้ดนี้ไหม?” แล้วตอบแบบสัญชาตญาณทุกครั้งว่า “เข้าใจ” คนแบบนั้นมักมั่นใจเกินไปและผิดบ่อย หากคำตอบคือ “ไม่แน่ใจ” คำถามถัดไปตามธรรมชาติก็คือ “ทำไม?” และคำตอบนั้นเองคือสิ่งที่ควรเขียนไว้ในคอมเมนต์
บางครั้งคำตอบคือ “เพราะคนอ่านอาจสงสัยว่าทำไมไม่เขียนอีกแบบ” ซึ่งเป็นกรณีพิเศษที่บทความนี้พูดถึง แต่บางครั้งคำตอบคือ “เพราะยังไม่ชัดว่ามันทำงานอย่างไรหรือทำไมถึงถูกต้อง” และในกรณีนั้นก็ต้องใช้คอมเมนต์อีกประเภทหนึ่ง
เรื่องแบบนี้มักเกิดตอนตัดแต่งสตริง หรือไล่สำรวจโครงสร้างข้อมูลแปลก ๆ ในขั้นกลาง
แค่ตัวระบุก็พาไปได้ไกลมาก แต่ไปไม่สุด ส่วนตัวผมชอบแนวทางที่บังคับให้เมธอด ตัวแปร ฟิลด์ และพารามิเตอร์สาธารณะมี documentation comment อย่าง jsdoc/xmldoc
การตั้งชื่อเมธอดให้ดีก็สำคัญ แต่การลองเขียนสั้น ๆ ว่ามันทำอะไรจะช่วยให้ชัดขึ้นกว่าเดิม และโดยเฉพาะช่วยเปิดเผยข้อบกพร่องที่เห็นได้ชัด หลายครั้งพอเริ่มเขียนประโยคแรกก็จะนึกชื่อที่ดีกว่าออกมาได้ และถ้าคำอธิบายเริ่มมีคำว่า “และ” ก็เป็นสัญญาณว่าเมธอดนั้นทำหลายอย่างเกินไปและควรถูกแยกให้เป็นตรรกะมากขึ้น
คนมักคิดว่า property ชัดเจนเกินกว่าจะต้องมีเอกสาร แต่
/** The API key */ string ApiKey;แบบนี้ขาดข้อมูลไปมากเกินไป เราไม่รู้ว่าคีย์นี้มาจากไหน ใช้ภายในอย่างเดียวหรือมีการรับส่งกับระบบภายนอก เป็นค่าบังคับหรือไม่ รับค่า null หรือค่าว่างได้ไหม มีความยาวสูงสุดหรือไม่ ถ้าค่าไม่ถูกต้องจะเกิดอะไรขึ้น หรือมีโค้ดหรือเอกสารให้ไปอ่านต่อไหมสำหรับคนที่เขียนเดิม ข้อมูลนี้ใช้เวลาเขียนแค่ 1–2 นาที แต่สำหรับคนมาใหม่ อาจต้องใช้เวลา หลายชั่วโมง กว่าจะหาคำตอบเจอเมื่อต้องแก้ไข นำไปใช้ หรือถูกดึงตัวมาซ่อมบั๊กในอีกหลายปีต่อมา
ถ้าพอเดาได้ว่าใน code review จะมีรีวิวเวอร์ที่ชอบซักละเอียดเกินไปท้วงอะไรบ้าง ผมก็มักเขียนคอมเมนต์ทำนองว่า “ไม่ได้ทำ X เพราะ Y” จุดประสงค์คือเพื่อลดการถกเถียงไปกลับที่น่ารำคาญ
คอมเมนต์ประเภท “แม้จะวนผ่านแต่ละสตริง 16 รอบ แต่ในหนังสือมีสตริงสูตรอยู่แค่ 25 รายการจนถึงตอนนี้ และส่วนใหญ่ยาวไม่ถึง 5 ตัวอักษร จึงเร็วพอ” ก็ยังมีรูปแบบแปรผันอีกแบบ
นั่นคือการใส่ debug log ที่จะทำงานเมื่ออินพุตโตเกินข้อจำกัดที่ตั้งใจไว้ตอนออกแบบเดิมมาก มันสื่อสารข้อความแทบจะเดียวกันกับนักพัฒนาในอนาคต แต่ตรวจพบได้เร็วกว่า จึงช่วยลดเวลาวินิจฉัยและดีบักได้มากกว่า
ถ้ามีระบบ logging และ observability ในอุดมคติ ก็คงวัดเวลาทุกองค์ประกอบของแอปและทิ้งข้อมูลดีบักไว้บ่อย ๆ แต่จะมีสักกี่คนที่ใช้ระบบสมบูรณ์แบบแบบนั้นจริง ๆ ความพยายามที่สำคัญกว่าคือการใส่ log แบบเจาะจงในจุดที่ประสิทธิภาพอาจแย่ลงภายหลัง หรือในส่วนที่ยังไม่มีเวลาปรับแต่งให้ดี
พอย้อนกลับไปมองก็เป็นไอเดียที่ obvious แต่ที่ผ่านมาแนวทางของผมคือทิ้งคอมเมนต์ไว้ในจุดที่ควรกลับมาดูทีหลัง แล้วหวังว่าถ้าเรื่องแย่ลงจะยังจำคอมเมนต์นั้นได้
ไม่ว่าใครจะว่าอย่างไร ก็ใส่คอมเมนต์และ doc comment ไว้ทั่วโค้ดค่อนข้างเยอะ แต่จะเริ่มแบบย้อนทาง คือเขียนคอมเมนต์สรุปรายการขั้นตอนของแอปพลิเคชันคร่าว ๆ ก่อน แล้วระหว่างพัฒนาก็ค่อยแตกขั้นตอนใหญ่ให้เป็นขั้นตอนย่อย ลบคอมเมนต์เดิมบ้าง เก็บไว้บ้าง และแยกคอมเมนต์ให้ละเอียดขึ้นเรื่อย ๆ จนเกือบกลายเป็นอัลกอริทึมที่เสร็จสมบูรณ์
ปกติเขียนโค้ดจากนอกเข้าใน จึงเขียนโค้ดไปพร้อมกับการแตกคอมเมนต์ด้วย บางครั้งก็โค้ดรวดเดียวก่อน แล้วค่อยมานั่งใส่คอมเมนต์ทีหลังในระดับที่คนส่วนใหญ่อาจขี้เกียจทำ ใส่คำอธิบายให้ทุกฟังก์ชันและตัวแปร และแม้แต่ฟังก์ชัน
deg_to_radก็ยังใส่"""Converts degrees to radians."""เพราะพื้นที่เก็บข้อมูลมันถูกรู้ว่าคนส่วนใหญ่ไม่ชอบ แต่ก็ไม่เป็นไร ถ้าไม่ชอบดูก็ลบออกด้วยสคริปต์หรือเอาออกตอน code review ได้ ถึงอย่างนั้นการอ่าน โค้ดเก่าของตัวเอง ก็ยังเพลินกว่าการอ่านโค้ดของคนอื่นที่ไม่มีคอมเมนต์มาก ใน Python โค้ด boilerplate เรียบ ๆ อย่าง Flask API มักจะ self-documenting อยู่แล้ว แต่บางทีโค้ด boilerplate แบบนั้นกลับเปลี่ยนบ่อยจนมีคอมเมนต์สำคัญกำกับไว้ ส่วนในอุตสาหกรรม งานฝั่งอัลกอริทึมมักถูกเขียนใหม่ทั้งก้อนบ่อยกว่า
ต่อไปก็ยังจะชอบคอมเมนต์และ doc comment อยู่ดี
ผมชอบสร้างภาพรวมทั้งระบบไว้ในหัว และรู้สึกว่าในช่วงแรกการลองเขียนตัวเลือกด้านการออกแบบหลายแบบจริง ๆ มันช้าเกินไป เพราะงั้นพอตัดสินใจเรื่องการออกแบบได้แล้ว ก็ต้องบันทึกไว้แน่นอน เพราะคนอื่นยังเข้าถึงสิ่งที่อยู่ในหัวผมไม่ได้
ส่วนรายละเอียด ผมคาดว่าคนอื่นจะเห็นชัดขึ้นเองเมื่อทำความเข้าใจภาพรวมเสร็จแล้ว แต่ถ้าด้วยเหตุผลบางอย่างการทำความเข้าใจนั้นไม่เกิดขึ้น มันก็อาจยิ่งอ่านยากขึ้นได้ จึงยังขัดเกลาเพิ่มเพื่อรักษาความอ่านง่ายพื้นฐานไว้อย่างน้อยที่สุด
หลายครั้งการอัปเดตคอมเมนต์ก็เป็นงานพอ ๆ กับการแก้โค้ด ดังนั้นในโลกความจริง คอมเมนต์จึงมักเป็นสิ่งที่ รอวันกลายเป็นคำโกหก อยู่เสมอ สุดท้ายคอมเมนต์กับโค้ดก็ไม่ตรงกัน และนั่นอาจแย่กว่าโค้ดที่ไม่มีคอมเมนต์เสียอีก
สู้ใช้ automated test ที่แสดงเจตนาไปเลยจะดีกว่า โดยทั่วไป test โกหกไม่ได้ และถ้ามันโกหกก็คงไม่ถูก merge อยู่แล้ว ถ้ามีชุด test ที่ดีพอแสดงให้เห็นว่าโค้ดตั้งใจให้ถูกใช้อย่างไร แบบนั้นทั้งอธิบายได้ดีและแทบรับประกันได้ว่าเป็นความจริง ซึ่งผมอยากเห็นมากกว่า
พอต้องกลับมาดูอีกทีหลัง 5 สัปดาห์ มันช่วยได้มาก
ผมยึดแนวคิดที่ว่า “คอมเมนต์คือคำขอโทษที่ส่งถึงตัวเองในอนาคต”
ถ้าโค้ดมันดูแปลก ช้า หรือเป็นส่วนที่พอจะอธิบายให้ใครฟังแล้วต้องพูดว่า “มันออกจะสะเปะสะปะหน่อยนะ” ผมก็มักจะทิ้งคอมเมนต์ไว้ โดยเฉพาะถ้าเคยลองแก้มันมาก่อน ก็จะบันทึกกรณีที่มันไม่ทำงานหรือสิ่งที่แก้ไปแล้วไว้ด้วย
ถ้าใช้เกณฑ์แบบนี้ คอมเมนต์ที่ไม่จำเป็นจะค่อย ๆ หายไปเอง และโดยมากจะเหลือแค่ตอนที่ควรบันทึก เหตุผลว่าทำไม จริง ๆ ลองใช้กับ codebase ของตัวเองสักประมาณหนึ่งเดือนแล้วจะเข้าใจความรู้สึกนี้