The Grug

https://knowyourmeme.com/memes/grug

เมื่อนานมาแล้วมีเพื่อนในทีม share บทความชื่อ The Grug Brained Developer พอลองอ่านดูผ่าน ๆ ก็คิดว่าคงเป็นแค่บทความตลก ๆ เขียนแบบปั่น ๆ อันนึง แต่เมื่อวันก่อนได้มีโอกาสย้อนกลับไปอ่านพบว่ามันเป็นบทความที่บอกเล่าถึงประสบการณ์ของผู้เขียนในฐานะ software developer กับแนวความคิดในการพัฒนา software ไว้ได้ดีมาก เลยขอแปลสรุปเป็นภาษาไทยเก็บไว้สักหน่อย (ลองอ่านต้นฉบับดูครับ ศัพท์ที่ใช้เขียนคือกวนมาก ฮ่า ๆๆ)

ศัตรูตลอดกาลของนักพัฒนา software คือ ความซับซ้อน

ทำไมน่ะหรอ เพราะวันนึงจาก code ที่อ่านเข้าใจง่าย ทุกอย่างทำงานได้หมด แต่เมื่อความซับซ้อน (complexity) เข้ามาใน code ทำให้ทุกอย่างจากดีกลายเป็นร้ายไปหมด แม้กระทั่ง debugger ก็ไม่สามารถช่วยเราหนีจากความซับซ้อนได้ ซึ่งคนที่สร้างมันขึ้นมาก็เป็น project manager หรือแม้กระทั่งบ่อยครั้งก็เป็นนักพัฒนา software เองด้วยซ้ำ!!

บางครั้งความซับซ้อนก็แกล้งนักพัฒนาที่แก้ code ส่วนเดียวแต่กลับไปพังส่วนอื่นที่ไม่เกี่ยวข้องด้วย แต่น่าจะเป็นเรื่องปกติสำหรับเรา ๆ เพราะมันก็เป็นส่วนนึงของงานนะ บางคนก็มองว่ายังดีกว่าไปทำงาน management รับเงินชิว ๆ ก็มี

Say “No”

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

Say “OK”

ในบางครั้งเราก็ปฏิเสธงานไม่ได้หรอกนะ ก็ต้องประนีประนอมกันไปไม่งั้นเราคงอดตาย ซ้ำร้ายไปกว่านั้นคือเราปฏิเสธไปแล้วแต่ management ก็ไม่แยแสหวังแต่ให้เราทำงานให้เสร็จก็พอ เมื่อเจอแบบนี้แล้วก็คงได้แต่พูดว่า “OK”

จากนั้นให้เราทำงานด้วยกฎ 80/20 โดย 80% ของ feature เกิดจากแรงที่ใช้ในการพัฒนาเพียง 20% เท่านั้น ถึงแม้มันจะดูชุ่ยแต่ก็ work นะ เพราะเราจะได้ focus กับการพัฒนา feature ที่สำคัญก่อนแล้วค่อยมาเก็บงานเล็ก ๆ อีก 20% ทีหลัง ซึ่งในบางครั้งเราอาจจะลดงานที่ไม่จำเป็นหรือต้องมาเก็บงานด้วยซ้ำ ในกรณีที่ 20% ของ feature ไม่คุ้มกับแรงที่จะต้องลงไปอีก 80% เมื่อเทียบกับ feedback จาก user

แต่ในชีวิตจริงนั้นน่าจะดีกว่าถ้าเราไม่บอก management ว่าเราใช้ 80/20 เพราะทำ 80/20 ไปแล้วเกิดมี bug แล้วค่อยมาขอโทษยังดีกว่าขอทำ 80/20 แล้วเค้าไม่ให้ แต่นั่นก็หมายความว่า project manager หลงลืมไปว่างานไหนสำคัญกว่าซึ่งฟังดูแย่กว่ามาก

การจัดการ code

ผู้เขียนเล่าว่าไม่สามารถแนะนำแบบกว้าง ๆ ได้เพราะ code แต่ละ project มันก็ต่างกันไป แต่มีสิ่งหนึ่งที่อยากแนะนำคือ

อย่าเพิ่งรีบด่วนจัดแบ่ง code ให้เป็นระเบียบ

เพราะในช่วงเริ่มแรกหลายสิ่งหลายอย่างมันยังดูไม่เป็นรูปเป็นร่าง เราจึงต้องเรียนรู้จากการพัฒนาไปเรื่อย ๆ ถึงจะเห็นภาพที่ชัดเจนขึ้น เช่น เมื่อเขียน code ก็คอยสังเกตว่ามันมีส่วนที่มีข้อมูลและพฤติกรรมคล้าย ๆ กันโผล่ขึ้นมาไหม เมื่อเห็นแล้วเราก็ค่อย ๆ refactor ไป มันก็เป็นเรื่องประสบการณ์ที่ต้องใช้ในการสังเกตได้ดีด้วย ดังนั้นขอให้เราอดทนฝึกฝนและเรียนรู้กับมันไป

แต่ในชีวิตจริง (อีกแล้ว) คนที่อยู่ในระดับสูงมองแต่ภาพรวมก็คงไม่ถูกใจสิ่งนี้และจะชี้บอกให้เราเริ่มสร้าง abstraction ตั้งแต่เริ่มแรก ซึ่งเราก็ควรจะตำหนินะเพราะว่าคนเหล่านั้นควรจะไปสนใจเรื่อง architecture มากกว่าแล้วให้เหล่านักพัฒนาดูแล code กันไป คนเหล่านี้ไม่ได้มานั่ง code กับเราซะหน่อย

แต่ถ้าไม่อยากตำหนิก็เสนอให้พวกเค้าทำ “prototype” ให้ดูหน่อยสิ เพื่อเป็นการควบคุมให้พวกเค้าลงมือทำและเข้าใจถึงปัญหาที่เหล่านักพัฒนาต้องเจอมากขึ้น เพื่อลดความเป็นไปได้ของพวกเค้าในการเพิ่มความซับซ้อนเข้ามาใน code ของเรา

การทดสอบ software

ผู้เขียนมีคำแนะนำเกี่ยวกับเรื่องการทดสอบดังนี้

  1. ให้เขียนชุดการทดสอบหลังจากที่ project ผ่านช่วง proptotype ไปแล้ว เพราะในตอนนั้น code ที่เขียนก็จะเริ่มมีคุณค่าในตัวมันเองแล้ว ยกเว้นในกรณีที่เกิด bug ให้เริ่มจากการทดสอบด้วย regression testing ก่อน
  2. อย่าข้ามการเขียนชุดการทดสอบเพียงเพราะมันทำงานบนเครื่องเราได้ แต่มันไม่ได้หมายความว่ามันทำงานบนเครื่องคนอื่นได้
  3. Test ทั้งหมดใน project จะให้ดีควรจะอยู่กึ่งกลางระหว่าง unit และ end-to-end test coverage ที่พอดี
  4. เขียน unit test ตอนเริ่ม project แต่อย่าเขียนเยอะไปแบบหวัง test coverage 100% เพราะสุดท้ายเมื่อมีการเปลี่ยนแปลงของพวกนี้ก็จะถูกโยนทิ้งไปอยู่ดี
  5. เมื่อ project เริ่มมีความเสถียรแล้วให้เพิ่ม integration test ที่อยู่กึ่งกลางระหว่าง unit และ end-to-end test
  6. ใน end-to-end test ให้เน้น case ที่สำคัญ ๆ เท่านั้น อย่าให้เยอะเกินไปเพราะจะดูแลรักษากันไม่ไหวนะ
  7. ใช้ mocking เท่าที่จำเป็นเท่านั้น

Agile

ผู้เขียนเล่าว่าเขามีความรู้สึกไม่ยินดียินร้ายกับ agile คือมันก็เป็นวิธีส่งมอบคุณค่าให้ business ที่ไม่ดีไม่แย่ แต่สิ่งที่น่ากลัวว่าคือผู้คนที่หมกหมุ่นกับ agile มากเกินไปต่างหาก เวลาที่ project มันไม่ประสบความสำเร็จ ก็มักจะมีคำพูดว่า

“ที่เราล้มเหลวเป็นเพราะเราทำ agile ไม่ถูกต้อง”

ทำให้ management คล้อยตามแล้วลงเอยด้วยการของบเพื่อไปฝึกรุ่นน้อง ๆ ต่อไป

คำแนะนำคืออย่าไปหมกหมุ่นกับ agile มากจนเกินไป สิ่งที่สำคัญกว่าในการพัฒนา software คือการทำ prototype, การเลือกใช้ technology และจ้างนักพัฒนาเก่ง ๆ ต่างหาก

Refactoring

Refactoring เป็นสิ่งที่ดีนะโดยเฉพาะตอนที่ code มันเป็นรูปเป็นร่างแล้ว แต่จงสังเกตว่า

  • ยิ่งเราต้องออกแรง refactor มากเท่าไร โอกาสที่จะล้มเหลวก็มากขึ้นตามไปด้วย สิ่งที่เราควรทำคือค่อย ๆ refactor ทีละเล็ก ๆ น้อย ๆ ระวังอย่าให้ออกทะเลไปไก
  • ถ้าเรามีจำนวนของ abstraction มากเกินไป มีโอกาสที่สูงที่การ refactoring จะล้มเหลว เช่น J2EE เป็นต้น
  • ถ้าเราเห็น code ที่อ่านยากน่าเกลียด ควรทำความเข้าใจระบบแล้ว code นั้นก่อนที่จะเข้าไปแก้ไขทุกอย่างให้ perfect ในทันที ไม่เช่นนั้นเราอาจจะเสียเวลาไปกับการวนแก้ไปเรื่อย ๆ ไม่มีที่สิ้นสุด เลวร้ายสุดคือลงเอยด้วยการไม่ได้อะไรกลับมาเลย

“The world is ugly and imperfect and many times and code must also be.”

เครื่องมือในการพัฒนา software

เครื่องมือที่ดีจะช่วยผ่อนแรงและช่วยคิดแทนเราได้ ดังนั้นเสียเวลาสักนิดเพื่อนเรียนรู้การใช้เครื่องมือเพื่อประหยัดเวลาในการพัฒนา software ไปได้หลายเท่า เช่น ใน IDE ก็ควรจะติดตั้ง autocompletion ไว้เพราะเราจะได้ไม่ต้องจำ API ทุกตัว (คนที่เขียนภาษา Java น่าจะเข้าใจดี เพราะถ้าไม่มีแล้วแทบจะเขียนกันไม่ได้เลย ฮ่า ๆๆ) หรือจะเป็นการเรียนรู้การใช้งาน Debugger ต่าง ๆ พวก breakpoint, evaluate expression เป็นต้น

ความซับซ้อนของ expression ใน code

ถ้าเรามี code แล้วต้องมาเปรียบเทียบว่า expression แบบไหนดีกว่า ให้เลือกอันที่มัน debug ง่ายกว่าไว้ก่อน เช่น

if(contact && !contact.isActive() && (contact.inGroup(FAMILY) || contact.inGroup(FRIENDS))) {
  // ...
}
  if(contact) {
    var contactIsInactive = !contact.isActive();
    var contactIsFamilyOrFriends = contact.inGroup(FAMILY) || contact.inGroup(FRIENDS);
    if(contactIsInactive && contactIsFamilyOrFriends) {
        // ...
    }
  }

สังเกตว่าแบบที่ 2 มัน debug ง่ายกว่า เพราะมันแยก expression ออกมาชัดเจนกว่า

Logging

  1. Log ตามเส้นทางเงื่อนไขที่สำคัญ (พวก if/for)
  2. ถ้า request ไหลไปหลาย service ใน cloud infrastructure ก็ให้เพิ่ม request ID ลงไปใน log เพื่อเวลาค้นหาจาก request ID จะได้ผลออกมาเป็นกลุ่ม log เดียวกัน
  3. ถ้าเป็นไปได้ให้เราสามารถกำหนด log level ได้เพื่อที่เราสามารถจะเปิด-ปิด log สำหรับการ debug ได้ จะดีไปกว่านั้นถ้าเราสามารถผูด log level กับ user ได้ในกรณีที่เกิด bug แล้วเราสามารถ debug บน production ได้ง่ายขึ้น

Concurrency

ถ้าเป็นไปได้ ให้เลือก concurrency model ที่เรียบง่ายที่สุดไว้ก่อน เช่น stateless web API หรือ worker queue ที่แต่ละ request ไม่ได้ยุ่งเกี่ยวกัน

APIs

คนส่วนใหญ่ที่สร้าง API มักจะไป focus ที่ implementation หรือ domain ที่ API เหล่านั้น serve แต่ไม่ค่อยคิดถึงตอนที่คนเอาไปใช้งานจริง น่าจะดีกว่าถ้าเราออกแบบ API ที่เรียบง่ายสำหรับ use case ที่เรียบง่าย แล้วออกแบบ API ที่ซับซ้อนสำหรับ case ที่ซับซ้อนดีกว่า

Front End

“I know, I’ll split my front end and back end codebase up and use a hot new SPA library talking to a GraphQL JSON API back end over HTTP.”

จากแนวประโยค classic ที่นักพัฒนาประสบการณ์น้อยมักจะพูดก่อนเริ่ม project โดยที่อาจจะไม่รู้ตัวว่าเขาได้เพิ่มความซับซ้อนเข้ามาในระบบแล้ว โดยเฉพาะโลกของ front-end ที่หมุนไปเร็วมาก บางทีมันก็หมุนตามบริษัท tech company ใหญ่ ๆ อย่าง Google (พัฒนาโดย Angular) หรือ React (พัฒนาโดย Facebook) ทั้งที่มันอาจจะไม่จำเป็นต้องใช้ library หรือ framework ที่มันซับซ้อน ต้องทำความเข้าใจ concept บางอย่างก่อน

คำแนะนำง่าย ๆ คือ ทำให้เรียบง่ายเข้าไว้ ใช้ HTML ธรรมดา ๆ ลด JavaScript file ให้ได้มากที่สุด ที่ตลกร้ายคือมันเป็นคำแนะนำที่ดีในมุมมอง technical นะ แต่เป็นคำแนะนำที่แย่ถ้าอยากหางานทำง่าย ๆ เพราะใคร ๆ เขาก็รับแต่คนเขียน tech stack พวกนี้เป็น ฮ่า ๆๆๆ

อีกคำแนะนำนึงคือกระแสของ tech ที่มาเร็วไปเร็วมักจะเกิดขึ้นในแวดวง frontend มากกว่า ดังนั้นเวลาเรียนรู้ tech ใหม่ ๆ ให้เผื่อใจไว้ด้วยว่ามันอาจจะไม่ใช่ไอเดียที่ดีแล้วมันอาจจะโดยขยำทิ้งไปเมื่อไรก็ได้

Fear Of Looking Dumb

เป็นเรื่องปกติที่คนเราจะพบกับ Fear Of Looking Dumb (FOLD) หรือ “อาการกลัวว่าคนอื่นจะมองว่าโง่” เลยไม่กล้าที่จะถามคำถาม หรือแย่ไปกว่านี้คือ “ทำไมระบบมันซับซ้อนจัง ช่างเถอะเราอาจจะโง่เองไม่เข้าใจก็ได้” ทำให้มีโอกาสที่ code มันจะเกิดความซับซ้อน หรือ ความซับซ้อนเหล่านั้นไม่ได้ถูกแก้ไขหรือเอาออกมาพูดคุยกัน

ส่วนตัวเราคิดว่ามันเป็นคำแนะนำที่ดีมาก ๆ สำหรับนักพัฒนาที่เพิ่งเริ่มเข้าสู่วงการ software สำคัญที่สุดคือขอให้เราสนุกกับเส้นทางนี้และเรียนรู้ไปกับมัน และที่สำคัญ “Complexity is very, very bad.”