ทำไมโปรแกรมเมอร์ส่วนใหญ่มักเขียนโค้ดแล้วอ่านไม่รู้เรื่อง แม้แต่ผมเองก็เถอะ เขียนแล้วมาอ่านอีกทีก็มึนไปซักพักเหมือนกัน วันนี้ผมเลยขอหยิบข้อแนะนำเล็กๆ น้อยๆ มาฝาก อ่านแล้วจะได้พึงสังวรณ์ก่อนเผางานครั้งต่อไปละกันนะครับ (--')
- อย่าพยายามทำเท่ห์ด้วยการใช้ left shift แทนการคูณด้วย 2 (อันนี้เคยเจอมากับตัว มันก็เท่ห์ดีนะ แต่งงอยู่นานเลยล่ะ)
- ช่วยตั้งชื่อตัวแปรให้มันสื่อความหมายหน่อย ถ้าใช้ภาษาระดับสูง (Java, .Net, PHP, etc.) ก็ตั้งชื่อให้มันอ่านออกและมีความหมายไปเลย
- วางแผนก่อนแล้วค่อยลงมือเขียนโค้ด เสียเวลาคิดสองนาที อาจจะช่วยไม่ให้คุณนั่งปวดหัวไปอีกหลายสัปดาห์
- โค้ดที่ไม่ใช้ให้ลบออกไปเลย อย่าคอมเม้นต์ทิ้งไว้ มันรกหูรกตา ถ้ากลัวว่าโค้ดเก่าจะหายไป ก็หัดใช้ SVN หรือ CVS ซะบ้าง
- อย่าคิดว่าทำแบบนี้ให้เสร็จไปก่อนวันหลังค่อยมาแก้ให้มันดี โค้ดที่คุณเขียนอาจถูกใช้งานนานกว่าที่คุณคิด (หรืออาจจะซับซ้อนจนไม่กล้าแก้!) ดังนั้นทำให้มันดีไปเลยดีกว่า
- ...และข้อสุดท้ายอย่าขี้เกียจ!!!
ทิ้งท้ายด้วยประโยคเด็ดจากหนังสือเล่มนี้
programs must be written for people to read, and only incidentally for machines to execute
ที่มา: blog.onlysimpler.com
Comments
จะว่าไปผมก็ไม่เคยใช้ cvs เลย เคยแต่ลงทิ้งไว้เฉยๆ แต่ไม่ได้ใช้
คนที่ใช้ left shift คงไม่ได้ใช้เพราะมันเท่ห์หรอกมั้งครับ แต่ใช้เพราะการ shift bit มันทำได้เร็วกว่าการใช้คำสั่งคูณ (ใช้ cpu cycles น้อยกว่า)
แต่ผมก็เห็นด้วยว่า ถ้าเขียนโปรแกรมทั่วๆ ไป ไม่ได้เน้นว่า จะต้องทำงานให้ได้เร็วที่สุด ก็ใช้คำสั่งคูณก็ดูจะเหมาะสมกว่า การใช้คำสั่ง left shift
ไม่เคยใช้ left shift เลย!
คิดว่า คอมไพล์เลอร์ฉลาด ๆ ส่วนใหญ่ ถ้าเจอ *2 ปุ๊บมันคงแก้ให้เป็น <<1 เลยอ่ะครับ (ทำ Optimizeไง)
เคยมีเขียนไว้ว่า กฎการ Optimize ข้อหนึ่ง ไม่ทำการ Optimize ถ้าไม่จำเป็น ...
หนังสือ pthread ก็มีนะครับ ประมาณว่าอย่าใช้ thread ถ้าไม่รู้ว่ากำลังทำอะไรอยู่ ------ LewCPE
lewcpe.com, @wasonliw
ถ้าจำเป็นก็เขียน optimizer/compiler เอง เพื่อแปลงไฟล์ที่คนอ่านรู้เรื่อง ไปสู้โค้ดที่ทำงานได้เร็วขึ้นแต่อ่านยาก เวลาแก้ก็แก้ที่ไฟล์อ่านรู้เรื่อง แล้วสั่งแปลงโค้ด
เป็นวิธีที่ดี... ถ้ามั่นใจว่าจะเขียน optimizer ไม่มีบั๊ก ไม่งั้น ได้ปวดหัวไปอีกหลายวัยแน่ๆ :D
---------- iPAtS
iPAtS
สัญลักษณ์ shift นี่ผมคิดว่าขึ้นอยู่กับความต้องการมากกว่า ผมชอบแอบหวังว่าคอมไพล์เลอร์มันจะช่วย optimize แต่หลายๆครั้งผมก็พบว่ามันไม่จริง ดังนั้นถ้าผมเขียนโปรแกรมที่ต้องการความเร็วสูงๆ ผมจะ optimize ส่วนสำคัญๆด้วยตัวเองก่อนส่งให้คอมไพล์เลอร์ (เช่นลบวงเล็บปีกกาใน C และ *2)
เฮอะๆ ประสบการณ์ที่เคยเจอนะครับ - เขียน C แล้ว include library ไม่ยอมเรียง A-z แล้ว include เป็นร้อย คนมาเขียนเพิ่มก็ดันใส่ซ้ำไปอีก... - เวลา link เป็น exe ก็ดัน link ทั้งหมด ทั้งๆที่ บาง link obj ก็ไม่ได้ถูกใช้ใน exe นี้ แต่ถูกใช้ใน exe อีกอัน - Function prototype ถ้าเป็น C แล้วมี output ก็จะ้เอาขึ้นก่อน เช่น strcpy(string_output, string_input); บางคนเขียนอันนึงขึ้นก่อน อันนึงไว้ด้านหลัง คือจะเอาอะไรขึ้นก่อนไม่ว่า ขอให้มัน follow standard library ของภาษาหน่อย
ประสบการณ์สุดปวดหัวของผมมีสองแบบ
- เจอโปรแกรมแบบกระโดดไปเรื่อยๆ เรียก function ไม่รู้จบ อ่านแล้วงงว่าตกลงที่กดตามเข้ามาแต่แรกมันตั้งใจจะทำอะไรกันแน่หว่า
- if ซ้ำ if ซ้อน ซ่อนเงื่อน เฉือนคม กว่าจะอ่านออกก็เหนื่อยแล้ว ที่เคยคิดจะแกะมาเขียนใหม่เป็นอันว่าช่างมันเหอะ ปล่อยมันไว้อย่างนี้แหละ แค่อ่านก็คลานแว้ววว
ปล. ไม่เคย optimize code เลยครับ
กำลังตอ้งแก้โค๊ดแบบนี้ ขอบอกว่านรกมากๆ ทรมาณ............
ผมว่าที่สำคัญที่สุดเลย คือต้องเขียนโค้ดให้ grep ได้ง่าย หลังๆเจอพวกเรียกฟังก์ชันโดยใช้ eval มั่ง pointer to function ไปเรียก pointer to member function อีกทีมั่ง ยิ่งพวก Python นี่มีแบบว่าสร้างชื่อฟังก์ชันเป็น string แล้วค่อย eval นี่เท่ชมัดแต่ไล่โค้ดลำบากจังเลย ถ้าจำเป็นต้องใช้ก็โอเคครับ แต่คิดก่อนใช้ก็ดี
อืม ใช้ทั้ง left shift กะ right shift เพื่อการคูณการหารเลย
แต่กลัวคนอื่นงงผมใช้ macro ช่วยหนะครับ แบบ
#define DOUBLE(var) var << 1 #define QUAD(var) var << 2 #define HALF(var) var >> 1
#define RESET(var) var ^ var
พอดีงานของผมมันอยู่บน Thin client หนะครับ แล้ว closs platform ด้วย ไม่รู้ว่า compiler ตัวไหนจะ optimize ให้ยังไงบ้างมั่ง
สงสัยครับว่า การใช้ left shift กับ right shift มันช่วยให้โปรแกรมทำงานเร็วขึ้นแค่ไหนครับ (ช่วยประมาณทีครับ)
จำข้อมูลละเอียดไม่ได้ จำได้แค่คร่าว ๆ ตั้งแต่สมัยเขียน assembly ว่าต่างกันพอสมควรครับ ลอง search ดู ได้ความว่าอย่างนี้:
เปรียบเทียบ clock cycle ของ 80x86 instruction set คำสั่ง SHL/SAL/SAR (shift) สำหรับ register 8 บิต ใช้เพียง 3 clock ใน 486 ส่วนคำสั่ง MUL/IMUL (คูณ) สำหรับ register 8 บิตใน 486 จะใช้ถึง 13-18 clock, DIV ใช้ 16 clock และ IDIV ใช้ 19 clock
ส่วนใน Pentium การกระทำเดียวกัน คำสั่ง shift ใช้เพียง 1 clock ส่วน MUL ใช้ 8, IMUL ใช้ 10, DIV ใช้ 17 และ IDIV ใช้ 22 clock
แต่ผมคิดว่า เรื่องการคูณ/หารด้วยการ shift นี่ คอมไพเลอร์ส่วนใหญ่น่าจะ optimize ให้อยู่แล้วนะครับ
เกี่ยวกับการ optimize.. ไม่ควรพยายาม optimize หยุมหยิมขณะเขียนโค้ด ร้อยทั้งร้อย มันไม่ช่วยอะไรหรอก นอกจากทำให้โค้ดอ่านยากขึ้นเท่านั้นแหละ
optimize ในระดับอัลกอริทึมจะเห็นผลชัดกว่า วิเคราะห์ Big-O function ให้ดีตั้งแต่ขั้น design (หรือ redesign) แล้วค่อยโค้ด
การ optimize ผิดที่ ก็ไม่ช่วยอะไร บางครั้ง จุดที่เป็นคอขวด อาจไม่ใช่จุดที่คิดไว้ก็ได้ เชื่อ profiler ดีกว่า
เมื่อพบคอขวดแล้ว optimize loop (เช่น ใส่ cut-off เพื่อตัดการวิ่ง loop เปล่าที่ไม่จำเป็น) ดีกว่า optimize expression
การ optimize expression จะให้ผลดีต่อเมื่อทำที่จุดที่วิกฤตที่สุดของโปรแกรมเท่านั้น
ปล. คำว่า "เท่" ไม่มี ห การันต์ นะครับ
สำหรับผมไม่มีอะไรจะปวดหัวไปกว่าไล่โคดของโปรแกรมเมอร์ที่กำลังบ้าเห่อ OOP โปรแกรมแทนที่จะเขียนให้ไล่ง่าย ๆ กลายเป็นว่ามี class อะไรก็ไม่รู้ที่ไม่จำเป็นเยอะแยะไปหมด โคดเรียกซ้อนลงไปไม่รู้ตั๊งกี่ชั่นกว่าจะเจอส่วนที่ทำงานจริง ๆ เดี๋ยวก็ Manager นั้น Manager นี้ เพียบไปหมด เขียนเป็น structural ก็เสร็จไปนานแล้ว
ถ้า OOP ได้ถูกต้องจริงๆ มันจะไม่ปวดหัวหรอกครับ ผมเองก็ต้องพยายามเตือนตัวเองเสมอเหมือนกัน ว่าอย่าสร้างคลาสใหม่ถ้ามันไม่จำเป็นจริงๆ เพราะปวดหัวเหมือนกันครับเวลาไล่โปรแกรมแบบนั้น กระโดดไปสิ แปดชั้น สิบชั้น งงจริงๆ
แต่อะไรก็ไม่นรกเท่า if ซ้อน if ซ้อน if ซ้อน if ซ้อน if ซ้อน .... (ล้อเล่นนะครับ สองชั้นจะเป็นลมแล้วครับ)
ผมว่าต่อให้ design ดียังไง ใช้ methodology ที่ดียังไง ถ้าระบบมันใหญ่และซับซ้อนจริง ถึงจุดหนึ่งมันก็ต้องซับซ้อนเกินว่ามนุษย์จะอ่านได้ง่ายๆอยู่ดี
ผมว่าแก้ปัญหาด้วยการทำ documentation น่าจะดีกว่านะ ถ้ามัวแต่หวังแต่จะงม code ลูกเดียว . . . . โอ๊ว . . . .
ปัญหาที่ผมเจอใน document คือเื่ชื่อถือไม่ได้ครับ แต่ก็ช่วยให้เข้าใจความตั้งใจของผู้เขียนได้ ใช้อธิบายคนอื่นๆ ในทีมที่ไม่ใช่โปรแกรมเมอร์ได้ ทีนี้ผมมองว่าสุดท้ายถ้าเป็นโปรแกรมเมอร์ จะมาใช้งานต่อ หรือจะมาแก้ไขโค้ด ยังไงก็ต้องอ่านโค้ด และสุดท้ายต้องทดสอบครับ (เทสคือพระเจ้า!!!)