- ซอฟต์แวร์มีหลายสิ่งที่ไม่แน่นอน
- ทำไมจึงไม่แน่นอน?
- เหตุผลที่ใหญ่ที่สุดคือความซับซ้อนของธุรกิจ
- ด้วยความซับซ้อนนี้ สถานการณ์จึงเปลี่ยนแปลงอยู่ตลอด และทำให้การคาดการณ์ของนักพัฒนามีโอกาสสูงที่จะผิดพลาด
- หอคอยที่สร้างอย่างทุ่มเทพังทลายลงและกลายเป็นหนี้ทางเทคนิคในทันที
- อีกเหตุผลหนึ่งคือการขาดความรู้และประสบการณ์
- หากไม่มีความรู้และประสบการณ์ นักพัฒนาอาจสร้างหนี้ทางเทคนิคขึ้นมาเองได้
- ความซับซ้อนของธุรกิจเป็นปัจจัยภายนอกที่นักพัฒนาไม่อาจควบคุมได้ ขณะที่ความรู้และประสบการณ์เป็นปัจจัยภายในที่นักพัฒนาควบคุมได้
- สำหรับนักพัฒนา มีอยู่สามเส้นทาง
- เส้นทางแบบมองโลกในแง่ร้ายที่คิดว่าการต่อสู้กับความซับซ้อนไร้ความหมาย
- จะเริ่มพูดว่า ‘เดี๋ยวก็เปลี่ยนอยู่ดี ทำๆ ไปเถอะ’, ‘เทคโนโลยีไม่มีความหมายหรอก’
- เพราะเป็นเส้นทางที่สบายและผ่อนคลาย จึงอาจเลือกเดินทางนี้โดยไม่รู้ตัว
- เส้นทางที่เพิกเฉยต่อความซับซ้อนและคิดถึงแต่ภาพอุดมคติ
- เชื่อว่าเทคโนโลยีเพียงอย่างเดียวที่ตนมองว่าเป็นอุดมคติสามารถแก้ได้ทุกอย่าง
- ทำให้เกิดกรอบความคิดที่แข็งทื่อและเป็นแบบเดียวกันหมด
- เป็นเส้นทางที่นักพัฒนาหลงเข้าไปได้ง่าย แต่ยากจะหลุดออกมา
- เส้นทางที่ยอมรับความซับซ้อนและต่อสู้กับมัน
- แม้ยอมรับว่าไม่มีวันสมบูรณ์แบบ ก็ยังคงพยายามค้นหาแนวทางที่ดีกว่าอยู่เสมอ
- เป็นเส้นทางที่ยากและต้องอดทน
- การพัฒนาซอฟต์แวร์ต่อสู้กับความซับซ้อนมาโดยตลอด
- สถาปัตยกรรม วิธีวิทยา Agile ฯลฯ
- แล้วสิ่งถัดไปที่จะเกิดขึ้นคืออะไร?
- การพัฒนาแบบมุ่งสู่การทำลาย
- เมื่อมองความเป็นจริง ก็ง่ายที่จะตกไปสู่ความคิดแบบสิ้นหวังว่าเดี๋ยวมันก็ถูกลบอยู่ดี
- เพราะการรู้สึกว่าโค้ดที่เราเขียนอย่างหนักกลายเป็นงานที่ล้มเหลว และต้องลบทิ้งด้วยมือตนเองนั้นเจ็บปวดมาก
- ถ้าอย่างนั้น ลองคิดกลับกัน แล้วทำให้มันลบได้ดีตั้งแต่แรก จะเป็นอย่างไร?
- การทำลายเป็นสิ่งที่ดีหรือไม่?
- หากไม่มีการทำลาย สิ่งใหม่ก็ไม่อาจถือกำเนิดขึ้นได้
- การทำลายที่พบได้ในซอฟต์แวร์มีอยู่ใหญ่ๆ สองแบบ - pivot และ refactoring
- Pivot ช่วยให้องค์กรและผลิตภัณฑ์เลือกเส้นทางที่ดีกว่าได้
- Refactoring เป็นสิ่งจำเป็นอย่างยิ่งเพื่อยืดอายุของซอฟต์แวร์
- แล้วการพัฒนาแบบมุ่งสู่การทำลายคืออะไร?
- เป็นวิธีวิทยาการพัฒนาที่ยอมรับข้อเท็จจริงว่าสักวันหนึ่งโค้ดจะถูกทำลาย และพัฒนาโดยมุ่งไปในทิศทางนั้น
- ยึดหลักใหญ่ 3 ข้อ
- หากมีความไม่แน่นอน ก็ลดความไม่แน่นอนนั้นลงให้ได้มากที่สุดเท่าที่ทำได้
- หากเลือกได้หลายวิธี ให้เลือกวิธีที่ทำลายได้ง่ายกว่า
- คงไว้เฉพาะสิ่งที่จำเป็น ดังนั้นสิ่งที่ไม่จำเป็นให้ลบทิ้งทั้งหมด
- วิเคราะห์ -> แยกขอบเขต -> ลงมือเขียนโค้ด -> กำจัดความซับซ้อน
- แก่นสำคัญคือการลดความไม่แน่นอนที่มาจากปัจจัยภายใน และเตรียมพร้อมต่อการทำลายที่เกิดจากปัจจัยภายนอกซึ่งหลีกเลี่ยงไม่ได้
- การแยกขอบเขต
- ความไม่แน่นอนคืออัตราการเปลี่ยนแปลง และสามารถใช้สิ่งนี้เป็นพื้นฐานในการแยกได้
- นักพัฒนาต้องเตรียมรับมือกับปัจจัยภายนอก พร้อมทั้งลดอัตราการเปลี่ยนแปลงที่เกิดจากปัจจัยภายในให้มากที่สุด
- เนื่องจากอัตราการเปลี่ยนแปลงของแต่ละปัจจัยอาจแตกต่างกันไปในแต่ละองค์กร จึงไม่สามารถแสดงเป็นตัวเลขตายตัวได้ -> ต้องวัดด้วยวิธีเชิงฮิวริสติก
- ต้องกำหนดระดับนามธรรมว่าจะใช้เกณฑ์ใดในการแยก
- ความสามารถในการถูกทำลาย
- เมื่อลงมือพัฒนา ให้เลือกทางที่ทำลายได้ง่ายตามหลักใหญ่
- สามารถประเมินความสามารถในการถูกทำลายได้โดยพิจารณาจากความเป็นอิสระ ความสามารถในการรับรู้เข้าใจ และความสามารถในการควบคุม
- ความเป็นอิสระพิจารณาจากระดับของ coupling และ cohesion รวมถึงยึดหลัก single responsibility principle ได้มากน้อยเพียงใด
- ความสามารถในการรับรู้เข้าใจคือระดับที่นักพัฒนาสามารถมองโค้ดแล้วเข้าใจได้
- ความสามารถในการควบคุมคือการพิจารณาว่าเป็นพื้นที่ที่นักพัฒนาควบคุมได้หรือไม่
- การกำจัดความซับซ้อน
- ต้องตรวจสอบว่ามีสิ่งที่ไม่จำเป็นหรือไม่ และกำจัดมันออกไป กล่าวคือท้ายที่สุดแล้วใน codebase ควรเหลือไว้เฉพาะสิ่งที่จำเป็น
- หากทำได้ยากเพราะปัญหาเรื่องเดดไลน์หรืออย่างอื่น ก็เพียงบันทึกไว้ก่อนแล้วค่อยจัดการภายหลังก็ไม่มีปัญหา
- เพราะปัจจัยภายในนั้นควบคุมได้
- แก่นสำคัญคือการรักษาความเรียบง่ายไว้ให้มากที่สุดเพื่อเตรียมพร้อมต่อการทำลาย
- เทคนิคของการทำลายโค้ด
- มีหลักการและวิธีการมากมายในการลบโค้ดให้ดี
- การแยกเป็นขั้นตอน (refactoring pattern)
- การรักษา referential transparency
- การยึดหลัก single responsibility principle
- การยึดหลัก interface segregation principle
- Strangler Fig pattern
- การทำ method specialization
- การเขียนโค้ดซ้ำ
- การบันทึกอัตราการเปลี่ยนแปลง
6 ความคิดเห็น
ผมไม่ค่อยเห็นด้วยกับคำพูดที่ว่าหนี้โค้ดเกิดขึ้นเพราะขาดความรู้และประสบการณ์
-> ผมคิดว่าสถานการณ์มีได้หลากหลาย เช่น อาจมีเวลาไม่พอสำหรับการทำตามข้อกำหนดที่ได้รับมา หรือในกรณีที่ทำงานร่วมกับผู้อื่น ก็อาจต้องยอมรับหนี้เชิงเทคนิคเล็กน้อยเพื่อให้ทำงานสอดประสานกันได้
และผมก็ไม่ค่อยเข้าใจเหมือนกันว่าทำไมถึงมองว่าความรู้และประสบการณ์เป็นปัจจัยภายในที่นักพัฒนาควบคุมได้
-> ธุรกิจมีความซับซ้อน จึงคาดเดาไม่ได้ว่าจะต้องเจอกับสถานการณ์แบบไหน และก็เป็นไปไม่ได้ที่จะศึกษาได้ครบทุกความเป็นไปได้ในแต่ละช่วงเวลา แม้จะไปศึกษาเมื่อเจอสถานการณ์นั้นจริง ๆ แต่ครั้งถัดไปก็อาจเกิดปัญหาใหม่ที่ต่างออกไปโดยสิ้นเชิง จนความรู้นั้นใช้การไม่ได้ก็ได้
สวัสดีครับ/ค่ะ ขอบคุณสำหรับความคิดเห็น
ผม/ฉันคิดว่าเราจะมองเห็นแก่นแท้ได้ก็ต่อเมื่อได้พิจารณาสิ่งที่สุดขั้วแล้ว ในแง่นั้น ผม/ฉันคิดว่าหากเข้าใจ
ความรู้และประสบการณ์อย่างสมบูรณ์ ก็จะสามารถสร้างโค้ดที่ไม่ใช่หนี้ทางเทคนิคได้ภายในเวลาที่กำหนดการที่เวลาไม่พอสามารถแบ่งได้เป็นสองกรณี กรณีแรกคือ เวลาที่จำเป็นต่อการลงมือพัฒนาไม่เพียงพอตามความหมายตรงตัว ในกรณีนี้ไม่ว่าจะแยกจากความรู้และประสบการณ์อย่างไร เวลาทางกายภาพสำหรับการเขียนโค้ดก็ไม่พออยู่ดี ดังนั้นจึงเป็นเงื่อนไขที่ทำให้บรรลุเป้าหมายไม่ได้ตั้งแต่แรก กรณีที่สองคือ ไม่มีเวลามากพอจะพิจารณาว่าอะไรดีกว่า ในกรณีนี้ เพราะไม่มีเวลาจะหาวิธีการสำหรับการพัฒนาหรือค้นหาทางเลือกที่ดีกว่า จึงจบงานด้วยการเขียนโค้ดจากความรู้ที่มีอยู่ในตอนนั้นเท่านั้น เมื่อทำงานเสร็จในลักษณะนี้ เราจะรู้ว่า
มีบางอย่างผิดพลาดอยู่แต่จะไม่รู้แน่ชัดว่าควรแก้อย่างไร หากมีความรู้ที่ถูกต้องอย่างแม่นยำ และมีความมั่นใจจากประสบการณ์เกี่ยวกับสิ่งนั้น ปัญหาแบบนี้ก็คงไม่เกิดขึ้นผม/ฉันคิดว่าเรื่องเวลาไม่พอที่เขียนไว้ข้างต้นเป็นสิ่งที่ช่วยสนับสนุนความเห็นของผม/ฉัน แน่นอนว่าในความเป็นจริงนี่เป็นปัญหาที่ยากมาก ผม/ฉันเพียงแค่พูดในเชิงอุดมคติเท่านั้น สภาวะที่มีทั้งความรู้และประสบการณ์อย่างสมบูรณ์นั้นเกิดขึ้นได้ยาก และอย่างที่คุณกล่าวไว้ ก็มีกรณีที่ต้องยอมรับมันโดยตั้งใจเพื่อองค์กรอย่างแน่นอน แม้อาจจะรู้สึกคับข้องใจ แต่ผม/ฉันมองว่าปัญหานี้
หากมองแบบสุดขั้วก็เป็นปัญหาที่เกิดขึ้นเพราะความรู้และประสบการณ์ยังไม่เพียงพอประเด็นที่สองเกี่ยวกับปัจจัยภายในที่คุณกล่าวมานั้นอธิบายได้ง่ายครับ/ค่ะ ตรงที่ว่า
ธุรกิจมีความซับซ้อน จึงไม่สามารถคาดเดาได้ว่าจะเกิดสถานการณ์แบบใดขึ้นมา …ส่วนนี้คือเรื่องความซับซ้อนของธุรกิจที่ผม/ฉันกล่าวถึงในบทความที่เขียนไว้ กล่าวคือ เป็นปัญหาที่เกิดจากปัจจัยภายนอก เพราะเป็นปัจจัยภายนอก นักพัฒนาจึงไม่สามารถควบคุมได้และรู้สึกหวาดกลัวต่อมัน เช่นกัน หากมองแบบสุดขั้วและสมมติว่าไม่มีความซับซ้อนทางธุรกิจ สิ่งที่เหลืออยู่ก็มีเพียงโค้ดที่นักพัฒนาเขียนเท่านั้น ถ้าเป็นเช่นนั้น ปัญหาที่เหลือก็จะมีเพียงเรื่องความรู้และประสบการณ์ซึ่งเป็นสิ่งที่ควบคุมได้จากภายในแน่นอนว่า บทความที่ผม/ฉันเขียนก็เป็นเพียงความคิดเห็นของผม/ฉันเท่านั้น ย่อมมีกรณีโต้แย้งได้มากพอ ผม/ฉันคิดว่าการแลกเปลี่ยนความคิดเห็นคือโอกาสที่จะพาเราไปสู่ทางที่ดีกว่า ต่อจากนี้ก็ขอฝากความคิดเห็นกันมาอีกมาก ๆ ด้วยนะครับ/ค่ะ ขอบคุณครับ/ค่ะ
ขอบคุณที่ตอบอย่างกรุณา
อ่านบทความแล้วชอบมากครับ/ค่ะ ดูเหมือนว่าอะไรจะนับเป็นการปรับแต่งเร็วเกินไปหรือเป็น overengineering ก็เปลี่ยนไปตามสเตจขององค์กรเหมือนกัน จุดที่ยากคือมันเป็นทั้งโค้ดที่ยังไงก็ต้องเขียนใหม่อยู่ดี แต่ก็เป็นโค้ดที่ไม่รู้ด้วยซ้ำว่าสุดท้ายจะมีจังหวะให้เขียนใหม่หรือเปล่า สำหรับผม/ดิฉัน บางครั้งก็ใช้คำถามว่า ถ้าบอกว่าบริการ xxx หรือฟีเจอร์นี้จะหายไป โค้ดกับข้อมูลของ yyy ควรอยู่ตรงไหนถึงจะเหมาะสม? เพื่อช่วยตัดสินใจเหมือนกัน เลยอยากรู้ว่าวิธีของคนอื่นเป็นอย่างไรบ้างครับ/คะ
ฉันมักจะคิดว่ามีอะไรนอกจากโค้ดบ้างที่อาจหายไปหรือเปลี่ยนแปลงได้ เช่น ข้อมูลหรือสคีมา
ผมก็อยากใส่เนื้อหาเกี่ยวกับข้อมูลลงไปด้วยเหมือนกัน แต่คิดออกได้ยากครับ เพราะเป็นส่วนที่สำคัญมาก เลยแตะต้องได้ไม่ง่าย และถ้าพลาดก็อาจตกไปสู่นรกของการทำ migration ได้ จึงต้องระมัดระวังครับ
อย่างที่คุณพูดไว้ ดูเหมือนว่าขั้นตอนการออกแบบตั้งแต่แรกสำคัญมากจริง ๆ และหัวใจสำคัญน่าจะเป็นการทำให้สามารถสะสม RAW ได้อย่างดีที่สุด หรือไม่ก็สถาปัตยกรรมแบบ event sourcing อาจได้เปรียบในแง่ของการลบก็ได้ครับ แน่นอนว่าผมเองก็ยังไม่เคยใช้งานสถาปัตยกรรมนี้อย่างจริงจัง เลยไม่แน่ใจว่ามันจะใช้ได้ผลจริงแค่ไหนครับ