(Strategic vs. Tactical Programming) (การเขียนโปรแกรมเชิงกลยุทธ์ vs. เชิงยุทธวิธี)

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

3.1 Tactical programming (การเขียนโปรแกรมเชิงยุทธวิธี)

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

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

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

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

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

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

3.2 Strategic programming (การเขียนโปรแกรมเชิงกลยุทธ์)

ก้าวแรกไปสู่การเป็นผู้ออกแบบซอฟต์แวร์ที่ดีคือการตระหนักว่า working code isn't enough. (โค้ดที่ทำงานนั้นไม่พอ) ไม่เป็นที่ยอมรับที่จะนำเข้าความซับซ้อนที่ไม่จำเป็นเพื่อให้งานปัจจุบันเสร็จเร็วขึ้น สิ่งที่สำคัญที่สุดคือโครงสร้างระยะยาวของระบบ โค้ดส่วนใหญ่ในระบบใด ๆ ถูกเขียนโดยการขยายฐาน โค้ดที่มีอยู่แล้ว ดังนั้นงานที่สำคัญที่สุดของคุณในฐานะนักพัฒนาคือเพื่อความสะดวกของส่วนขยายในอนาคต ดังนั้น คุณไม่ควรคิดว่า "โค้ดที่ทำงาน" เป็นเป้าหมายหลักของคุณ แม้ว่าโค้ดของคุณต้องทำงาน เป้าหมายหลักของคุณต้องคิดออกแบบที่ยอดเยี่ยม ซึ่งก็เกิดขึ้นว่าทำงานได้เช่นกัน นี่คือ strategic programming (การเขียนโปรแกรมเชิงกลยุทธ์)

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

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

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

3.3 How much to invest? (ลงทุนมากแค่ไหน?)

แล้วอะไรคือจำนวนการลงทุนที่ถูกต้อง? การลงทุนครั้งใหญ่ในตอนแรก เช่น การพยายามออกแบบระบบทั้งหมด จะไม่มีประสิทธิผล นี่คือ Waterfall method และเรารู้ว่ามันไม่ทำงาน การออกแบบในอุดมคติมักจะเกิดขึ้นในส่วนน้อย เมื่อคุณได้รับประสบการณ์กับระบบ ดังนั้นวิธีที่ดีที่สุดคือการลงทุนเล็ก ๆ น้อย ๆ มากมายอย่างต่อเนื่อง ผมแนะนำให้ใช้เวลาประมาณ 10–20% ของเวลาพัฒนาทั้งหมดของคุณในการลงทุน จำนวนนี้มีขนาดเล็กพอที่จะไม่ส่งผลกระทบอย่างมีนัยสำคัญต่อตารางเวลาของคุณ แต่มีขนาดใหญ่พอที่จะสร้างผลประโยชน์ที่มีนัยสำคัญเมื่อเวลาผ่านไป โครงการเริ่มต้นของคุณจะใช้เวลา 10–20% นานกว่าที่พวกเขาจะใช้ในวิธีเชิงยุทธวิธีที่บริสุทธิ์ เวลาพิเศษนั้นจะส่งผลให้ออกแบบซอฟต์แวร์ที่ดีกว่า และคุณจะเริ่มสัมผัสประโยชน์ภายในไม่กี่เดือน ไม่นานมาก่อนที่คุณจะพัฒนาอย่างน้อย 10–20% เร็วกว่าที่คุณจะทำถ้าคุณเขียนโปรแกรมเชิงยุทธวิธี ณ จุดนี้การลงทุนของคุณจะกลายเป็นฟรี: ผลประโยชน์จากการลงทุนในอดีตของคุณ จะประหยัดเวลาเพียงพอเพื่อครอบคลุมค่าใช้จ่ายของการลงทุนในอนาคต คุณจะได้รับการชดเชยต้นทุนของการลงทุนเริ่มต้นอย่างรวดเร็ว Figure 3.1 แสดงปรากฏการณ์นี้

img

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

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

3.4 Startups and investment (Startup และการลงทุน)

ในสภาพแวดล้อมบางอย่าง มีกองทัพที่แข็งแกร่งที่ทำงานต่อต้านวิธีการเชิงกลยุทธ์ ตัวอย่างเช่น Startup ในระยะแรกมีความกดดันอย่างมากในการได้รับการปล่อยตัวในช่วงแรกออกมาอย่างรวดเร็ว ในบริษัทเหล่านี้ ดูเหมือนว่าแม้แต่การลงทุน 10–20% ก็ไม่คุ้มค่า ผลลัพธ์ที่ได้ Startup หลายแห่งใช้วิธีการเชิงยุทธวิธี ใช้ความพยายามน้อยลงเพื่อการออกแบบ และใช้ความพยายามน้อยลงเพื่อให้ทำความสะอาดเมื่อปัญหาเกิดขึ้น พวกเขาให้เหตุผลนี้กับความคิดที่ว่า ถ้าพวกเขาประสบความสำเร็จ พวกเขาจะมีเงินพอที่จะจ้างวิศวกรเพิ่มเติมเพื่อทำความสะอาด

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

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

Facebook เป็นตัวอย่างของ Startup ที่ส่งเสริมการเขียนโปรแกรมเชิงยุทธวิธี ตลอดหลายปี สำนวนของบริษัท คือ "Move fast and break things" วิศวกรใหม่ที่เพิ่งจบจากวิทยาลัยได้รับการสนับสนุนให้บ้านทันทีเข้าไปในฐาน code ของบริษัท เป็นเรื่องปกติสำหรับวิศวกรที่จะ push commits เข้ากระบบสำหรับเครื่องบ้านแรกของพวกเขา ในด้านบวก Facebook ได้รับชื่อเสียงของบริษัทที่ให้อำนาจให้กับพนักงาน วิศวกรมีความกว้างขวาง และไม่มีกฎเกณฑ์และข้อจำกัดมากมาย

Facebook ประสบความสำเร็จอย่างมากเป็นบริษัท แต่ฐาน code ของมันได้รับความเสียหายเนื่องจากวิธีการเชิงยุทธวิธีของบริษัท มากมายของโค้ดไม่เสถียรและยากที่จะเข้าใจ มีความเห็นจำนวนน้อยหรือการทดสอบ และเจ็บปวดที่จะทำงานด้วย เมื่อเวลาผ่านไป บริษัทก็สำนึกว่ามีวัฒนธรรมที่ไม่สามารถดำรงไปได้ ท้ายที่สุด Facebook เปลี่ยนสำนวนของมันเป็น "Move fast with solid infrastructure" เพื่อสนับสนุนให้วิศวกรของมันลงทุนมากขึ้นในการออกแบบที่ดี จะเห็นว่า Facebook จะสำเร็จในการทำความสะอาดปัญหาที่สะสมมาตลอดปีของการเขียนโปรแกรมเชิงยุทธวิธี

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

โชคดีที่ มันเป็นไปได้ที่จะประสบความสำเร็จใน Silicon Valley ด้วยวิธีการเชิงกลยุทธ์เช่นกัน Google และ VMware ขึ้นมาประมาณเวลาเดียวกับ Facebook แต่บริษัททั้งสองนี้ยอมรับวิธีการเชิงกลยุทธ์มากขึ้น ทั้งสองบริษัทวางน้ำหนักหนักต่อโค้ดคุณภาพสูงและการออกแบบที่ดี และทั้งสองบริษัทสร้างผลิตภัณฑ์ที่ซับซ้อนซึ่งแก้ไขปัญหาเชิงซับซ้อนด้วยระบบซอฟต์แวร์ที่เชื่อถือได้ วัฒนธรรมทางเทคนิคที่แข็งแกร่งของบริษัทกลายเป็นที่รู้จักสูงใน Silicon Valley บริษัทอื่นไม่กี่บริษัทสามารถแข่งขันกับพวกเขาสำหรับการจ้างผู้บุคลากรทางเทคนิคด้านบน

ตัวอย่างเหล่านี้แสดงว่าบริษัทสามารถประสบความสำเร็จด้วยทั้งวิธี อย่างไรก็ตาม มันสนุกสนานมากขึ้นที่จะทำงานในบริษัทที่ใจใจการออกแบบซอฟต์แวร์และมีฐาน code ที่สะอาด

3.5 Conclusion (สรุป)

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

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