Mentoring/Coaching

อันนี้เป็นความเห็นส่วนตัวกับเรื่องของการ Mentoring/Coaching นะครับ ผมแทบไม่เคยทำเรื่องพวกนี้มาก่อนในที่ทำงาน กับข้างนอกก็ทำบ้างนิด ๆ หน่อย ๆ แต่ก็ไม่ได้จริงจังเพราะว่าเขาก็ไม่ได้มาขอให้เราเป็น 555

ผมคิดว่า จริง ๆ ไม่ว่าใครก็ต้องการ mentor หรือ coach สักคน เป็นที่ปรึกษาในเรื่องงาน (ขนาด Eric Schmidt อดีต CEO ของ Google ยังมี mentor เลย) สองคำนี้ความหมายอาจจะต่างกันพอสมควร แต่เท่าที่เห็นในที่ทำงานก็มักจะใช้ในความหมายคล้าย ๆ กัน ก็คือเป็นคนคอยสอนงาน คอยเป็นที่ปรึกษา โดยทั่วไปเวลาที่เราเข้าไปร่วมงานในบริษัทใหม่ ๆ หัวหน้าจะกำหนดให้พนักงานที่เป็นตำแหน่งอาวุโสกว่า (โดยทั่วไปก็คนที่มีคำว่า “senior” อยู่ในชื่อตำแหน่งนั่นแหละ) มาเป็น mentor ให้ แต่ผมพบว่าพอเวลาผ่านไปประมาณครึ่งปี mentor คนนี้ก็จะเริ่มถอยออกไป มันก็เป็นเรื่องน่าเสียดายเหมือนกัน คือผมเชื่อว่าคนเรากว่าจะชำนาญงานอะไรก็ตามจะใช้เวลาประมาณ 3 ปี (ถ้าสอนกันถูกวิธีนะ) อย่างน้อยก็ควรอยู่ด้วยกัน 3 ปีนั่นแหละ

แต่หลายคนก็จะบอกว่า เฮ้ย ก็ทำงานที่เดียวกัน เวลามีอะไรจะเดินเข้าไปถามเมื่อไหร่ก็ได้

ประโยคข้างบนมีส่วนถูกครับ แต่ก็มีส่วนที่ผิดเช่นกัน ผมเชื่อว่าหน้าที่ของ mentor คือการเดินเข้าไปหา mentee (คนที่ถูก mentor) ครับ ซึ่งกลับกับความเชื่อของคนส่วนใหญ่เลยนะ ผมคิดว่าคนสอนควรเป็นคนเข้าหา โดยเฉพาะในระยะแรกนี่ต้องนั่งประกบแทบทั้งวันเลยล่ะครับ ไม่ใช่ว่าต้องนั่งรอให้ mentee เดินเข้ามาหา เหมือนเป็นฤาษีต้องให้ลูกศิษย์ต้องเข้าป่าไปหา

เพราะถ้ารอให้คนอื่นเข้าไปหาเวลาที่จำเป็น ไม่ต้องเป็น mentor ก็ได้ครับ ใครในทีมก็ถามได้ทั้งนั้นแหละ พอเวลาผ่านไปปุ๊บ mentor จะถูกลืม และนั่นคือความผิดพลาดของ mentor ที่กลายเป็นคนที่ไม่มีส่วนในความสำเร็จของ mentee เลย

อีกเหตุผลหนึ่งคือ ในระยะแรกๆ ของพนักงานใหม่ เขาไม่กล้าเข้าใกล้ใครทั้งนั้นล่ะครับ สภาพแวดล้อมใหม่ ๆ คนใหม่ ๆ เขายังอยู่ในช่วงปรับตัว ถ้าเขายังถูกคาดหวังว่าต้องเดินเข้าหาคนที่ตัวเองไม่รู้จักเอาเองมันก็ไม่ต่างอะไรกับการถูกทิ้ง ว่าไหมครับ ? (กับคนที่เข้าสังคมเก่ง ๆ ก็คงไม่มีปัญหาอะไร แต่ผมคิดว่าพนักงานเก่าก็มีหน้าที่ในการช่วยให้คนใหม่สามารถปรับตัวได้เร็วด้วยล่ะนะ)

ทีนี้คนเป็น mentor เขาสอนอะไรกันบ้าง ?

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

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

ว่าแต่ถ้าแค่รอให้ mentor เดินเข้ามาหา ผมว่าคงมีหลายคนไม่เดินไปหาหรอก 55 ผมเชื่อว่าการถามสารทุกข์สุขดิบกันบ้างนาน ๆ ครั้งก็สำคัญ เชื่อเถอะครับ คำถามง่าย ๆ อย่าง เป็นไงบ้างช่วงนี้ มันสามารถพาไปยังปัญหาที่เขากำลังประสพอยู่ได้ดีนะ (ผมก็ถามประจำ) อาจจะแกล้งเดินผ่านไปเจอ หรือแบบหยุดคุยกันเล่น ๆ ในครัวก็ได้ ไม่ลำบากเกินไปหรอกครับ (ผมทำบ่อย 55)

ทีนี้เราจะเป็น mentor กันจนถึงเมื่อไหร่ดี ? ส่วนตัวผมคิดว่าเป็นไปได้เรื่อย ๆ จนกว่าจะคิดว่าตัวเองทำไม่ได้แล้ว อย่างสมมติผมเป็นโปรแกรมเมอร์แต่ mentee ดันบอกว่า อยากเป็น CEO อันนี้ผมก็คงช่วยอะไรไม่ได้เพราะว่าผมก็ไม่รู้ว่า CEO เขาทำอะไรกันบ้าง 555 ก็คงสอนอะไรไม่ได้ ถ้าให้คำปรึกษาบ้างก็คงตอบได้ แต่ผมก็ไม่รู้ว่าจะให้คำปรึกษาเขาอย่างไรให้เขาสามารถพัฒนาตัวเองขึ้นไปเป็น CEO ได้เหมือนกัน อันนี้จนปัญญา ก็คงต้องบอกว่าให้เขาไปขอให้ CEO สักคนมาเป็น mentor ให้จะดีกว่า

สุดท้ายนี้ผมก็เชื่อว่า การเป็นคนสอน การเป็นที่ปรึกษานั้นก็เป็นการพัฒนาตัวเองเช่นกัน การสอนคนอื่นเป็นการทบทวนความรู้ความสามารถของตัวเอง ดังนั้นการเป็น mentor เองก็ทำให้เราได้รับอะไรบางอย่างเช่นกัน ผมคิดว่า ถ้าทำได้ และไม่ติดขัดอะไร ถ้าหามีคนมาขอให้เป็น mentor หรือได้รับมอบหมายให้ทำหน้าที่นี้ ก็อย่าปฎิเสธเลยครับ

ใช้ async สำหรับสร้างฉาก now loading

ก่อนอื่นเกริ่นก่อนว่า ผมมีคลาสที่ชื่อว่า Scene สำหรับแต่ละฉากในหนึ่งเกม (ไม่รวมฉากย่อย ๆ อันนั้นต้องจัดการเอาเอง) โดยแต่ละฉากในเกมก็จะเป็นคลาสย่อยของคลาสนี้ และแต่ละฉากจะต้องรับหน้าที่สร้างฉากต่อไปหลังจากที่มันทำงานเสร็จแล้ว (ถูกเรียกผ่าน Scene::NextScene())

ทีนี้ ปัญหาคือ ถ้าเราให้ Scene::NextScene() โหลดฉากใหม่ขึ้นมา โปรเซสจะหยุดทำงานจนกว่าฉากนั้นจะโหลดเสร็จ ซึ่งอาจจะกินเวลานานมาก ๆ เราจึงต้องมีกลไกรองรับการโหลดรีซอร์สในอีกเธรดหนึ่งในขณะที่เธรดหลักจะยังวาดอะไรสักอย่างบนจอเพื่อบอกว่า “กำลังโหลดไฟล์อยู่ รอเดี๋ยว” อยู่ ผมก็เลยสร้างคลาสชื่อว่า LoaderScene ขึ้นมา (โค๊ดอยู่ข้างท้าย)

คลาสนี้เองก็เป็นคลาสที่สืบทอดมาจาก Scene อีกต่อหนึ่ง ตัวมันเองไม่ได้ทำอะไรมากมาย แค่เรียกใช้ฟังก์ชั่น std::async ภายใน std::async ผมก็สั่งให้มันสร้างวัตถุใหม่ออกมาในอีกเธรดหนึ่ง ตัว LoaderScene จะถูกแสดงผลบนจอจนกระทั่ง std::async ทำงานเสร็จ และมันจะบอกตัวโปรแกรมหลักที่เรียกมันว่ามันทำงานเสร็จเรีบร้อยแล้ว เพื่อให้โปรแกรมหลักเอาวัตถุใหม่ที่สร้างเสร็จแล้วไปใช้นั่นเอง

คลาสนี้จะไม่วาดอะไรบนจอ (แค่แสดงผลเป็นจอดำ ๆ) ถ้าเราต้องการให้มันแสดงผลอะไรสักอย่าง ก็สร้างคลาสย่อยขึ้นมาอีกอันนึง โดยระบุให้มันวาดอะไรสักอย่างบนจอ แค่นั้นเองไม่ยากใช่ไหมครับ 🙂

สำหรับโค๊ดเต็ม ๆ นั้นก็อยู่ข้างล่างนี่ล่ะครับ

#ifndef GAME_LOADERSCENE_H
#define GAME_LOADERSCENE_H

#include <future>
#include "./Scene.h"

namespace pgengine {

template <class S> class LoaderScene : public Scene {
public:
  LoaderScene() {
    future = std::async(std::launch::async, []() { return new S; });
  }

  virtual bool IsCompleted() {
    if (!future.valid())
      return false;
    auto status = future.wait_for(std::chrono::milliseconds(10));

    return status == std::future_status::ready;
  }

  Scene *NextScene() { return future.get(); }

private:
  std::future<S *> future;
};
}
#endif // LOADERSCENE_H

Unit Test คืออะไร ?

ไปตอบคำถามในฟอรัมหนึ่ง เรื่องของ Unit Test เขาถามว่ามันคืออะไร ผมก็อธิบายไปประมาณนึง เห็นว่าน่าสนใจก็เลยเอามาแชร์ให้ฟังพร้อมเพิ่มเนื้อหา

Unit test คือการทดสอบตัว Code Unit โดยทั่วไปอาจจะหมายถึง ฟังก์ชั่น หรือเมธอด การทดสอบนั้นมีเพื่อเอาไว้ยืนยันว่าแต่ละยูนิทนั้นทำงานได้ถูกต้อง

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

สมมติ เช่น ผมมีฟังก์ชั่นที่คืนค่าสัมบูรณ์ของ input ใด ๆ

int absolute(const int& a);

ผมสามารถเขียนโปรแกรมเพื่อทดสอบฟังก์ชั่นนี้ได้ดังนี้

void test_absolute() {
  assert(absolute(10) == 10);
  assert(absolute(-5) == 5);
  assert(absolute(0) == 0);
}

ถ้าโปรแกรมเราทำงานไม่ถูกต้องก็จะพัง ถูกไหมครับ พอเรารู้ว่ามันพังเราก็จะรู้ว่า อ๋อ ฟังก์ชั่นนี้ทำงานผิดนะ เราก็ต้องแก้โปรแกรม ซึ่งเราจะแก้แล้วรันใหม่กี่ครั้งก็ได้ตามแต่ที่ต้องการ

ในปัจจุบันการทำ Unit Test จะอาศัย Unit Testing Framework ในการสร้างโปรแกรมขึ้นมาเป็นชุดการทดสอบ (Unit Test Suite) โดยตัวที่ได้รับความนิยมก็คือ jUnit ของภาษา Java ซึ่งก็แตกยอดออกมากลายเป็นตระกูล xUnit ในหลาย ๆ ภาษาครับ

หน้าตาของ Unit Test ที่เขียนด้วย jUnit ก็ไม่ต่างอะไรกับตัวโปรแกรมทดสอบของผมข้างบนสักเท่าไหร่ เช่น ผมอาจจะมีเมธอดสำหรับตรวจสอบที่อยู่อีเมล์

Utility.validateEmailAddress(String address)

ก็สามารถเขียนตัว Unit Test ได้แบบนี้

class ValidateEmailAddressTest {
    @Test
    void testValidateEmailAddress() {
        Utility utility = new Utility();
        assertTrue("mr_tawan@hotmail.com is valid", 
                   utility.validateEmailAddress("mr_tawan@hotmail.com"));
        assertFalse("mr_tawan is invalid",
                   utility.validateEmailAddress("mr_tawan"));
    }
}

เมื่อตัว unit test นี้ถูกเรียกใช้งาน ถ้าหากว่ามีเทสต์เคสไหนที่ไม่ผ่าน ตัวฟังก์ชั่น assert* จะโยน exception ออกมาเพื่อให้รู้ว่ามันมีปัญหาครับ

การใช้ framework มีข้อดีที่ว่ามี output ที่แน่นอน ทำให้สามารถใช้เครื่องมือในการอ่าน output ออกมาเพื่อแสดงผลเป็นรายงานได้ด้วย (เช่น IDE แทบทุกเจ้ารองรับ jUnit หมด)

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

ในหลาย ๆ โปรเจคจะมีกำหนดเอาไว้ว่า ทุก ๆ วันหลังจากที่ทุกคนกลับบ้าน จะมี server ตัวนึงที่ดึงโค๊ดออกมาจาก repository เพื่อที่จะรัน Unit Test Suit ที่เก็บเอาไว้กับโค๊ดนั้น ๆ และจะมีรายงานออกมาว่าโปรแกรมมีปัญหาหรือไม่ ในอีกหลาย ๆ โปรเจคนั้เนตัว Unit Test จะทำงานทันทีหลังเช็คอินอีกต่างหาก นี่คือสิ่งที่การทำ Unit Test ด้วยมือไม่สามารถทำได้แน่นอน