เทคนิคเกี่ยวกับการใช้ if …. else (ตอนที่ 2)

มาพูดเรื่องเดิม ๆ แต่ว่าเป็นเนื้อหาใหม่ครับ พูดเป็นเรื่องสั้น ๆ อีกสักสองเรื่องละกัน

ไม่ควรใช้ if (not…) then … else

ผมว่ามันตลกนะ ถ้าแบบมีคนสั่งว่า “ถ้าไม่มีป้ายบอกทางว่าเลี้ยวซ้ายผ่านตลอด ให้หยุดรอสัญญาณไฟ นอกเหนือจากนั้นแล้วให้เลี้ยวซ้ายผ่านไป” ..

คือมันเป็นการใช้ปฎิเสธซ้อนปฎิเสธน่ะครับ ถ้าเป็นคนปรกติพูดเราก็จะพูดกันว่า “ถ้ามีป้ายบอกว่าเลี้ยวซ้ายผ่านตลอดก็เลี้ยวซ้ายผ่านไป แต่ถ้าไม่มีให้หยุดรอสัญญาณไฟ” มากกว่าใช่ไหมครับ 

เวลาเขียนโปรแกรมก็เหมือนกัน ผมคิดว่าเราไม่ควรใช้ปฎิเสธซ้อนปฎิเสธครับ อย่างโค๊ดข้างล่างนี่ 

if(!recordAvailable())
    createNew();
else   
    updatePresent();

เวลาเขียนก็ควรเป็นแบบนี้มากกว่า

if(recordAvailable())
    updatePresent();
else
    createNew();

ผมว่ามันอ่านง่ายกว่านะ

ใช้ if(not success) เพื่อออกจากโปรแกรม แทนที่จะใช้ if(sucess) แล้วทำต่อ

หลาย ๆ ฟังก์ชั่นจะคืนค่าเป็น error code กลับมา ถ้าเกิดว่าเราเขียนว่า if (success) แล้วทำต่อเนี่ยมันจะกลายเป็นการสร้าง  statement ย่อย ๆ เพิ่ม พอยิ่งพ่วงกันยาว ๆ แล้วมันก็จะยิ่งเพิ่มระดับของ statement  ไปเรื่อย ๆ จะทำให้โค๊ดอ่านยากครับ

อย่างเช่นโค๊ดแบบนี้

int init()
{
    if(initVideo() == SUCCESS) 
        {
            if(initAudio() == SUCCESS)
            {
                if(initDatabase == SUCCESS)
                {   
                    return SUCCESS;
                }  
            }  
        } 
    cleanUp(); 
    return FAILED;
}

เกิดมีสัก 10 ฟังก์ชั่นนี่ตายเลย แถมเขียนผิดไปสักระดับหนึ่งนี่ไล่หากันไปเถอะครับ เขียนแบบนี้แทนอ่านง่ายกว่าเยอะครับ

int init()
{
    if(initVideo() == FAILED)
    {  
        cleanUp();
        return FAILED; 
    } 
    if(initAudio() == FAILED) 
    {  
        cleanUp();  
        return FAILED; 
    }   
    if(initDatabase == FAILED) 
    {  
        cleanUp();  
        return FAILED; 
    } 
    return SUCCESS;
}

ง่ายกว่าเห็นไหมครับ ? ที่จริงก็ดูมันซ้ำซ้อนกันบ้าง แต่ว่าแบบนี้เราจะหาจุดที่ผิดพลาดได้ง่ายกว่ามากครับ

Dependency Manager

ผมคิดว่าทุกคนที่ทำงานในด้านสายซอฟท์แวร์น่าจะคุ้นเคยกับ Version Control System นะครับ (ผมเคยพูดไปก่อนหน้านี้แล้วนิดหน่อย) วันนี้จะมาพูดถึงซอฟท์แวร์อีกตัวหนึ่งที่ทำงานคู่กับ VCS เจ้านี่มีชื่อว่า Dependency Manager

Dependency คืออะไร ?

ในการเขียนโปรแกรม dependency หมายถึงโปรแกรมที่ไม่ได้เป็นส่วนหนึ่งของโปรแกรมของเรา แต่โปรแกรมของเรามีการเรียกใช้งานครับ

หรือถ้าจะพูดให้รู้เรื่องขึ้นมาอีกนิด มันก็คือบรรดา library ทั้งหลายที่เราเรียกใช้นั่นล่ะครับ

dependency อาจจะเป็นแค่อีกโปรแกรมหนึ่งที่เราเขียนขึ้นมาเอง อยู่ใน workspace/solution เดียวกันก็ได้ (เรียกว่า Internal Dependency) หรือจะเป็นโปรแกรมอื่นที่คนอื่นเขียนแล้วเราเรียกขึ้นมาใช้ (External Dependency)

พอสังเขปก็ประมาณนี้ล่ะครับ

Dependency Manager คืออะไร

Dependency Manager คือซอฟท์แวร์ที่ใช้ในการจัดการบรรดา Dependency ของโปรแกรมที่เราเขียน … แปลกำปั้นทุบดินอีกแล้ว

ที่ว่าจัดการก็คือ มันจะสามารถอ่านไฟล์ Dependency Description ของโปรเจคที่เราทำงานอยู่ว่าใช้ Dependency ตัวไหน เวอร์ชั่นไหน และจะไปทำการไปหา Dependency ที่ว่านี้มาจาก Dependency Repository มาเพื่อใช้งานกับตัวโปรเจคเราครับ และทุกครั้งที่ตัว description มีการเปลี่ยนแปลง มันก็จะทำการเปลี่ยนแปลงบรรดา dependency ที่เราใช้ให้เป็นไปตามที่กำหนดเอา เพื่อไม่ให้การคอมไพล์โปรแกรมมีปัญหาครับ

แล้วเราเก็บ Dependency ไว้ใน VCS ไม่ได้เหรอ ?

ที่จริงในอดีตก่อนจะมี Dependency Manager ใครๆ ก็เก็บพวก library file ทั้งหลายเอาไว้ใน VCS กันล่ะครับ

ปัญหาก็คือ เวลามีคนเช็คอินไฟล์เข้าไปจะไม่มีใครรู้ว่าไฟล์ที่เอาเข้าไปมันเก่ากว่า หรือใหม่กว่า เป็นเวอร์ชั่นที่ไม่ compatible กันเลยหรือเปล่า หรือที่แย่กว่านั้นคือเอาไฟล์ที่เสียเข้าไปด้วยซ้ำ

ในทางปฎิบัติแล้ว ไฟล์ที่อยู่บน VCS ควรเป็นไฟล์ที่สามารถ diff ได้ เพื่อที่จะหาความแตกต่างระหว่างเวอร์ชั่นได้ ไม่เช่นนั้นถึงเราจะมีการเก็บประวัติเอาไว้แต่ก็ไม่รู้ว่าแต่ละเวอร์ชั่นมันต่างกันอย่างไร ก็ไม่มีประโยชน์ครับ

การใช้งาน Dependency Manager มีประโยชน์ตรงที่เราสามารถที่จะแทร๊คได้ว่าเราเคยใช้ Dependency ไหนเวอร์ชั่นไหนบ้าง (เพราะเก็บไฟล์ Dependency Description) เราจะได้รู้ว่ามีใครเล่นแผลง ๆ ใส่ dependency ผิด ๆ ลงมาบ้าง และถ้ามีการต้องเปลี่ยนเวอร์ชั่นของ dependency ก็แค่ตั้งค่าใหม่ ตัวระบบจะไปดึงลงมาให้เอง ไม่ต้องเปิดเวปแล้วหาว่าจะไปโหลดจากเวปไหน ลดโอกาสที่จะเกิดความผิดพลาด และประหยัดเวลาลงไปได้อีกครับ

ประโยชน์อีกอย่างก็คือ เมื่อโปรเจคเราเป็น library ซึ่งทำมาเพื่อให้คนอื่นใช้งานเป็น dependency เราสามารถใช้ Dependency Manager ในการเผยแพร่ library ของเราขึ้นไปบน Dependency Repository ได้ เราไม่ต้องมานั่งก๊อปไฟล์ไปให้โปรเจคอื่นแล้วต้องมานั่งลุ้นว่าเขาจะโหลดของเราไปใช้ได้อย่างราบลื่นหรือเปล่า

ตัวอย่างของ Dependency Manager

ซอฟท์แวร์ประเภทนี้ที่พอจะมีชื่อหน่อยก็คงเป็น Apache Ivy ซึ่งเป็นโปรเจคย่อยของ Ant อีกต่อครับ

แต่นอกจากนี้แล้ว ซอฟท์แวร์ประเภท Build Automation หลาย ๆ ตัวก็มีความสามารถในการจัดการ dependency ในตัว เช่น Apache Maven, Gradle เป็นต้นครับ

ก็ลองดูกันนะครับว่าจะใช้ Dependency Manager ที่เป็นส่วนหนึ่งของ Build Automation หรือใช้ตัวที่เป็น standalone โดยส่วนตัวผมจะใช้ตัวที่รวมกับ Build Automation ในกรณีที่ใช้ Build Automation ครับ ซึ่งปรกติผมก็ไม่ค่อยใช้นะ (แต่ควรใช้ครับ เดี๋ยวคราวหน้าจะพูดถึงในโอกาสต่อไป)

[ความพยายาม] ไม่ได้มีค่ามากอย่างที่คุณคิด

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

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

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

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

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

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