Unity Application Block  #1: กว่าจะมาเป็น Unity 

  
     Unity เป็น Framework ตัวหนึ่งซึ่งอยู่ในชุดของ Enterprise Library ของ Microsoft ซึ่ง Enterprise Library เป็นชุด Framework สำเร็จรูป ที่ไม่ผูกพันกับเนื้องาน สามารถนำเอาไปใช้ได้เลยในงานต่างๆ  Framework เหล่านี้ได้รับการออกแบบมาอย่างดี ตามหลักการของ Object-Oriented Design ทาง Microsoft ใช้งานชุดนี้เป็นการเผยแพร่แนวคิด Object-Oriented มี Source Code ให้ศึกษาอีกด้วย  Framework แต่ละตัวในชุด เรียกว่า Application Block ดังนั้น Unity  ที่ผมจะพูดถึงในวันนี้ ชื่อเต็มของมันก็คือ Unity Application Block และวันนี้ผมจะเน้นเฉพาะ ตัว Unity แค่ตัวเดียว ตัวอื่นค่อยหาเวลานำเสนอต่อไปครับ

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

เริ่มจากความต้องการและปัญหา

    การพัฒนา Software นั้นมีหลายประเภท ตั้งแต่เกมส์ไปจนถึงงานธุรกิจ  ซึ่งถือว่าเป็นขั้วตรงข้ามกัน ทั้งในแง่ความรู้สึกเวลาใช้งานและแนวทางที่ใช้ในการพัฒนา  ว่าไปแล้วที่ยอดนิยมกัน ผมว่ากว่า 90% ที่เขียนโปรแกรมกัน ก็คืองานทางธุรกิจ (Enterprise Applications) ก็ธุรกิจมันเป็นตัวผลักดันทุกอย่างนี่ ซึ่งถ้าเปรียบเทียบกับการพัฒนาเกมส์แล้ว เขียนง่ายกว่าเยอะครับ แต่งานทางธุรกิจนี้ ความยากไม่อยู่ที่การเขียนครับ ยากตรงไหน ใครไม่เคยเขียนไม่รู้ อธิบายไป ก็อาจจะไม่เห็นภาพ ผมเลยขอยกตัวอย่างเปรียบเทียบ ที่มันผุดขึ้นมาในหัวตอนเขียนบทความนี้ แล้วผมก็อุทานออกมาว่า "ใช่เลย"

    ย้อนกลับไปประมาณ 200 ปีที่แล้ว สมัยต้นรัตนโกสินทร์ ในช่วงนั้นถ้าไปดูที่ฝั่งยุโรป  กองกำลังนโบเลียนแข็งแกร่งถึงขีดสุด รบไหนชนะที่นั่น กองกำลังที่ชื่อว่า "Grande Armee" หรือมีชื่อเป็นอังกฤษว่า Grand Army ที่มีทหารนานาชาติผสมกันเกือบ 700,000 คน  ปี ค.ศ. 1812  นโบเลียน กรีฑาทัพใหญ่ที่สุดจาก "Grande Armee" ประมาณ 400,000 กว่าคน เข้าตีรัสเซีย ในสงครามที่มีชื่อว่า Patriotic War of 1812 ระหว่างทางเข้าตีนั้น แน่นอนครับ บุกไปที่ไหนก็เป็นชนะที่นั่น ข้าศึกคงเกรงถอยนี้ไปหมด จนสุดท้ายบุกถึงเมือง มอสโคว ข้าศึกทิ้งเมืองหนีหมด กลายเป็นเมืองร้าง ใครสนใจอยากรู้ว่าตอนนั้นรัสเซียคิดอะไรอยู่ อะไรเกิดขึ้นทางฝั่งรัสเซียบ้าง ผมแนะนำให้ลองอ่านนิยายเล่มใหญ่เล่มหนึ่งครับ War and Peace (สงครามและสันติภาพ) ของ สีโอ ตอลสตอย ซึ่งอิงประวัติศาสตร์หลังเกิดเหตุประมาณ 50 ปี

    นักรบอยากรบแต่ไม่ได้รบ ข้าศึกหนีหมด ชนะไม่จริง ไม่น่าภูมิใจ สุดท้ายก็คลุ้มคลั่งเผาเมืองมอสโควไปเกือบราบ ยังครับเรื่องนี้ยังไม่จบตรงนี้ ถ้าจบกันตรงนี้ วันนี้สงสัยว่า Keyboard ของผมที่กำลังพิมพ์อยู่นี้ คงเป็นเป็นภาษาฝรั่งเศสแทนอังกฤษไปแล้ว ในเมืองมอสโควเวลานั้น เป็นเมืองเปล่า เปล่าจริงๆ เสบียง ก็ไม่มี นโบเลียนเตรียเสบียงมาจำกัด หมายไปหาเอาข้างหน้า แต่เจอกลยุทธ์นี้แล้ว ก็หนักครับ นี่เป็น Case Study ที่ใช้ในวิชา Logistics เลยครับ รบโดยไม่ส่งเสบียง ไม่น่าเชื่อว่าว่ากิ้งกือจะหกล้มขนาดนี้ เคราะห์ซ้ำกรรมซัดครับ  หิมะเพิ่งเริ่มตกครับ ลางร้ายเริ่มมาเยือน นโปเลียนรู้แล้วว่าอะไรจะเกิดขึ้นต่อไป รีบสั่งถอนทัพกลับฝรั่งเศสทันที
   
    ซวยหนักขนาดนี้ยังไม่พอครับ โดนซวยสองชั้น ปีนั้นเกิดปรากฏการณ์ลานีญ่าอีก อากาศแล้ง จะหนาวหนักกว่าทุกปี อุณหภูมิตกลงไปถึง -40 C สำหรับทหารที่ไม่ได้เตรียมเครื่องกันหนาวมาพอ มาจะขนาดไหนหนอ ยังครับยังซวยต่อเนื่องชั้นสาม รัสเซียใช้กลยุทธ์ "ตีชิงตามไฟ" เข้าตีรังควาญ จนกองทัพต้องหนีหัวซุกหัวซุน ให้ทายเล่นๆ ครับ เหลือกลับไปถึงฝรั่งเศษสักเท่าไร ถ้าใครไม่รู้มาก่อนคงเดาไม่ถูกครับ เหลือแค่หมื่นต้นๆ ที่เหลืออีก สี่แสน ถูกหิมะกัดตาย บางคนกินเนื้อพวกเดียวกันเพราะขาดเสบียง พวกที่รอดน่าจะเป็นพวกทหารม้าครับ ถอยได้เร็ว  พวกทหารราบน่าสงสาร ตายหมด แต่เหตุการณ์นี้ยังเป็นบทเรียนที่ไม่พอ เยอรมัน ภายใต้การนำของ ฮิตเลอร์ หลังจากนั้นไปอีกประมาณ ร้อยกว่าปี ก็ทำผิดพลาดเช่นเดียวกันนี้อีกครั้ง โดยเข้าตีรัสเซียอีก keyboard ผมก็เลยเป็นภาษาอังกฤษ จนทุกวันนี้ แทนที่จะเป็นภาษาเยอรมัน
1812


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

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

    ในการเขียนโปรแกรมทางธุรกิจนี้ สิ่งที่นักพัฒนาต้องการก็คือ อะไรที่ใช้ง่าย อ่านง่าย ใช้ง่าย แก้ง่าย ไม่ซับซ้อน ใครมาอ่านก็รู้เรื่อง ซึ่งมันตรงข้ามกับงานที่ต้องเผชิญ มันซับซ้อนขึ้นทุกวัน นักคิดต่างๆ จึงคิดต่อยอดกันมาเรื่อยๆ ทั้งด้านเครื่องมือ คือภาษา แนวคิดในการเขียนโปรแกรมต่างๆ หรือด้านการจัดการ ก็คือพวก Methodology ต่างๆ ก็ถูกการสร้างขึ้นมาเพื่อการนี้หลายอย่าง ในบทความนี้ ผมคงเน้นแค่มุมมองเดียว ก็คือ แนวคิดในการเขียนโปรแกรมเท่านั้น ส่วนอื่นขอละเอาไว้
 
     แนวคิดทางการเขียนโปรแกรม ก็เริ่มต้นจาก Imperative Language (Procedural) พวก C, Pascal ก็สามารถทำงานซับซ้อนได้ในระดับหนึ่ง งานบางงานที่ซับซ้อนมากเช่น OS ที่มี Code หลายล้านบรรทัด ก็ยังใช้ภาษา C เขียนได้ แต่นั่นก็คงต้องพึ่ง Programmers ที่เก่งมากๆ ซึ่งคนส่วนมาก (อย่างผม) คงไม่สามารถทำได้ ดังนั้นทุกวันนี้แนวคิดต่างๆ จึง ถูกพัฒนาขึ้นเพื่อให้โปรแกรมเมอร์ส่วนใหญ่ที่มีความสามารถระดับกลางๆ สามารถเอาชนะงานที่ซับซ้อนได้ ในทุกวันนี้ แนวคิดหลักมุ่งไปทาง Object-Oriented  แต่ก็นั่นแหละ ถึงแม้ว่าแนวคิด Object-Oriented จะมีมากว่า 30 ปีแล้ว แต่ด้วยความซับซ้อนในการทำความเข้าใจ และซับซ้อนในการประยุกต์ เลยดูเหมือนว่า Object-Oriented ที่ใช้เป็นเครื่องมือในการลดความซับซ้อน กลับกลายเป็นตัวสร้างความซับซ้อนเสียเอง ก็เลยเป็นที่มาของเรื่องต่อไปต้องปรับปรุงแก้ไขกันต่อไป

Interface-Based Programming

    ต้นยุค 90 แนวคิด Object-Oriented เริ่มได้รับความนิยม แนวคิดต่างๆ ก็เริ่มมีการนิยาม ลองผิดลองถูก และเผยแพร่ให้รู้กันในวงกว้าง ในยุคนั้น นักพัฒนา Software เริ่มเรียนรู้คำว่า Coupling ซึ่งหมายถึงการที่คนสองคนหรือของสองสิ่ง มีความสัมพันธ์กัน ถ้าใช้ในคนความเป็น "เพื่อน" ก็สามารถใช้คำว่า Coupling ได้ และดีด้วย แต่ไม่ใช่ในโลกของ Object-Oriented คำว่า Coupling มองในแง่ลบ ยิ่งในภาษา C++ มีการใช้งาน keyword "friend" ยิ่งแย่ใหญ่  จริงๆ แล้วยังมีปัญหาอื่นๆ อีกเยอะ แต่เนื่องด้วย Unity ออกแบบมาแก้เรื่องปัญหาการ Coupling ผมเลยขอเน้นที่ประเด็นนี้ประเด็นเดียว
  
     แน่นอนครับ การลดความซับซ้อนนี้ วิธีหนึ่งก็คือลด Coupling ให้มากที่สุด  แยก Class ออกจากกัน ไม่เกี่ยวข้องกันมากเท่าไหร่ก็ยิ่งดี ดีที่สุดคือไม่มี Coupling เลย คือเราสามารถมอง Class แต่ละ Class อิสระต่อกัน การเขียนโปรแกรมจะง่ายมาก ไม่ซับซ้อน เพราะเรามองแค่ class เดียว ไม่ต้องคำนึงถึง Class อื่นเลย แต่ในทางปฏิบัตินั้น เป็นไปไม่ได้ ถ้ามนุษย์ในโลกนี้ไม่มีปฏิสัมพันธ์กันเลย คงอยู่กันไม่ได้ ถ้า class มันไม่สัมพันธ์กันเลย มันก็ไม่เป็นโปรแกรมเช่นกัน สิ่งที่เราทำได้้ก็เพียงลดความสัมพันธ์ให้มากที่สุด  หรือพูดอีกนัยหนึ่งว่าให้ความสัมพันธ์ของมันหลวมที่สุดเท่าที่เป็นไปได้ (Loosely Coupling)
   
    การลด Coupling นอกจากลดความซับซ้อนแล้ว ยังช่วย ให้ Code สามารถ Reuse ได้ เราสามารถนำเอาไปใช้กับงานอื่นได้ ไม่ผูกพันกับงานได้งานหนึ่ง (Application Block ที่ผมกล่าวถึงข้างต้น ก็เป็นตัวอย่างที่ดี) การแก้ไขก็ง่ายอีกด้วย
   
    วิธีการลด Coupling ที่นิยมกัน ก็คือการ นิยาม Interface ขึ้นมา คุยกันผ่าน Interface แทนที่จะคุยกับ Class โดยตรง ยกตัวอย่างเปรียบเทียบ กับร้านสะดวกซื้อ เราซื้อของโดยไม่ได้สนใจว่าใครเป็นผู้ขาย เอาของวาง เขาบอกเท่าไหร่ก็จ่ายเท่านั้น รอเงินทอน รอใส่ถุง ทั้งหมดนี้คือ Interface มาตรฐาน (ยกเว้นบางช่วงมีการแจกแสตมป์ที่เอาไว้ส่งจดหมายไม่ได้) ไม่ว่าร้านสะดวกซื้อจะเปลี่ยนใครมาเป็นพนักงาน ระบบนี้ก็ยังคงอยู่  ผิดกับร้านผัดไทหน้าปากซอย ผมเรียกแกว่าตี๋มาตั้งแต่เด็ก ทั้งที่แก่อายุมากกว่าผมเกือบ 20 ปี ตอนนี้ก็ยังเรียกอย่างนั้นอยู่ พอเห็นผมก็รู้ทันทีว่าจะสั่งอะไร เติมน้ำตาล พริกป่น น้ำส้ม ในกระทะเลย ทานทีไรได้รสชาติเดิมไม่มีผิดเพี้ยนเลย มองเป็นข้อดีใช่ไหมครับ แต่มันไม่ดีก็ตรงที่มีวันนึงเฮียแกไม่อยู่ เมียแกทำแทน วันนั้นแย่ครับ สั่งกันไม่ถูกเลย สุดท้ายรสชาติออกมาไม่ไหวเลยครับ ผมคง Coupling อยู่กับเฮียแกแน่ๆ เลย

    ในยุคนั้นบางสำนักสั่งสอนให้ การเขียนโปรแกรม Class แต่ละ Class จะไม่ติดต่อกันโดยตรง ต้องติดต่อกันผ่าน Interface เท่านั้น (C++ ไม่มี keyword interface ก็ใช้ pure virtual Class แทน) ยุ่งยากหน่อย แต่ก็พอไหว แต่ติดปัญหาตรงที่ ตอนสร้าง Object นั่นเอง ลองดูตัวอย่างครับ

    ICar car = new Toyota();
    car.start();
    car.stop();

    โปรแกรมนี้ไม่มีปัญหา ICar เป็น Interface การใช้งาน ICar นี่ เราลดระดับความ Couple จากการไป Couple กับ Class Toyota ไป Couple กับ Interface ICar แทน ในอนาคต เราเปลี่ยนยี่ห้อรถ เป็น Honda ก็แทบไม่ต้องแก้อะไรเลย เพราะเรานิยาม Interface มาตรฐานเอาไว้แล้ว ยกเว้นบรรทัดแรกครับ ความเป็น Toyota() ยังคงเหลืออยู่ มันต้องมีวิธีที่ดีกว่านี้สิน่า

Design Patterns

        มีกลุ่มโปรแกรมเมอร์อยู่กลุ่มนึ่ง  เขียนโปรแกรมโดยใช้แนวคิด Object-Oriented มายาวนาน ลองผิดลองถูกมาเยอะ จนกระทั่งมีประสบการณ์ในการลดการ Coupling รู้ว่าเขียนอย่างไรให้เกิด Coupling น้อย ก็เลยรวบรวมเอามาเขียนเป็นหนังสือ โดยเลือกเฉพาะแนวคิดที่พบบ่อยๆ มีใช้ในหลายโครงการ แต่ก็ไม่กล้าที่จะเรียกมันว่าเป็นสูตร เรียกว่า Patterns ก็แล้วกัน ยึดหลัก เมื่อเจ้าตัวใช้แล้ว "work" คนอื่นก็น่าจะใช้แล้ว "work" เช่นกัน  หนังสือเล่มนี้เขียนตั้งแต่ปี 1994 นานมากแล้วครับ จนทุกวันนี้ Patterns หลายตัว ก็ถูกคนอื่นปรับแก้ไปแล้วเยอะ ตามกาลเวลาครับ ผมขอเชียร์ให้ออก 2nd Edition ซักที แต่ก็ยังไม่เห็นมีวี่แววซะที

    จากตัวอย่างข้างบน ถ้าเราจะเขียนให้ Coupling น้อย เราอาจใช้ Pattern ที่ชื่อว่า Factory Method ดังนี้

    ICar car = factory.CreateCar();
    car.start()
    car.stop()
 
    จะเห็นว่า เราไม่เห็น Toyota อยู่ใน Code นี้เลย ที่ไหนต้องการ car เราก็ใช้ factory มาสร้างให้  พอมาซักวันจะเปลี่ยนจาก Toyota เป็น Honda ก็เปลี่ยนที่เดียว ดูดีขึ้น

Enterprise Java Beans (EJB)

    คงไม่เกินความจริงไปนัก ถ้าจะกล่าวว่า ถ้าในอดีตไม่มี EJB วันนี้ก็คงไม่มี Unity ในเมื่อเรื่องมันเกี่ยวข้องกัน ผมก็ขอเอาเรื่องนี้มาขยายหน่อย ขอเริ่มตรงนี้ก็แล้วกัน เป็นที่ทราบกันดีว่า .NET นั้นเกิดจากการเลียนแบบตัว JDK ของ Java  มันเหมือนกันในระดับ JVM กับ CLR เท่านั้น  แนวทางในการพัฒนาต่อยอดของทั้งสองค่ายนั้ินต่างกันค่อนข้างมาก ทาง Java จะเน้นเรื่องแนวคิดของ Object-Oriented เน้นการทำ Software ขนาดใหญ่ แต่ทางฝั่งของ Microsoft จะเน้นที่ความง่าย ใครๆ ก็เขียนได้ ใครๆ ก็เขียนเป็น
   
    ทาง Java มีการแบ่ง Spec Framework สำหรับงานขนาดใหญ่โดยเฉพาะ โดยเรียกว่า Java Enterprise Edition มีองค์ประกอบหลายส่วน แต่ส่วนที่เกี่ยวข้องกับเรื่องวันนี้คือ Enterprise Java Beans (EJB)   แนวคิดของ EJB เป็นแนวคิดที่น่าสนใจ ก็คือความพยายามสร้าง Framework ที่มี Coupling ที่ต่ำมาก Reuse ได้เยอะ แถมทำทีเดียวได้ความสามารถอื่นๆ เยอะ  เช่น Persistent, Distributed System, AAA และอื่นๆ อีกมาก

    การทำเช่นนี้ได้ ต้องอาศัยสิ่งที่เรียกว่า Container แนวคิดของ Container นี้น่าสนใจ มันเปลี่ยนจากการเขียนโปรแกรมแบบปกติ เข้าสู่ Event-Driven Programming ว่าไปแล้วตัวของ Container คือ ภาชนะที่ใช้ในการบรรจุ Components (กลุ่มของ Classes) โดยที่โปรแกรมเราแทนที่จะสั่งงาน Library ต่างๆ มาทำงาน เรากลับเขียน Components เก็บไว้ใน Container รอให้ Container มาเรียกใช้กลับหัวเป็นหางกลับหางเป็นหัว เราเขียนโปรแกรมเปลี่ยนจากเจ้าบ้านเป็นแขกแทนเสียนี่ แต่การเขียนโปรแกรมแบบนี้ ความสามารถมันไม่ได้ลดลงนะครับ ความสามารถของโปรแกรม ก็เพิ่มขึ้นตามความสามารถของ Container แต่ภายใต้เงื่อนไขว่า คุณต้องยอมรับ "กรอบ" ของ Container นั้น

     ว่าการตามหลักแล้ว Container ใช้แนวคิด ของ Enterprise Pattern ตัวหนึ่งที่ชื่อว่า Inversion of Control  (IoC) โดยที่ Container จะควบคุม Main Program เอาไว้  ส่วนเราเขียน Code  ดัก Event เท่านั้น  ถ้าว่ากันไปแล้ว  Windows Form ของ Visual Basic ตั้งแต่รุ่นแรก ก็ใช้แนวคิด IoC นี้ คุณสามารถสร้าง ปุ่มกด แล้วให้มัน Pop up คำว่า Hello, World โดยใช้คำสั่งเพียงคำสั่งเดียว   แตกต่างกับการเขียนโปรแกรมแบบเดิม ถ้าใช้ภาษา C โปรแกรมเดียวกันนี้อาจใช้ถึง 200 บรรทัด ซึ่งคุณต้องตรวจสอบทุกอย่างเอง ผิดกลับใน Visual Basic ทั้งหมดจะเป็นหน้าที่ของ Windows Form เท่านั้น คุณเพียงเขียนเฉพาะส่วนที่เป็นเนื้องานจริงๆ เท่านั้น  จะเห็นได้ว่าแนวคิด IoC นี้ช่วยลดความยุ่งยากของ Code ให้มันซ่อนอยู่ใน Container ได้เยอะทีเดียว ขอดีของ Java Enterprise Edition อีกข้อก็คือ ไม่ผูกพันกับ Vendor นั่นคือวันนี้ใช้ Container ของ Sun พรุ่งนี้เปลี่ยนไปใช้ของ Oracle ได้ โดยที่ไม่ต้องแก้โปรแกรมในส่วนของภาษา Java เลย

     มาดูแนวคิดของการสร้าง Object ตามแบบ EJB ดูบ้าง ใช้แนวคิดข้างต้น จึงยืดหยุ่นมากมี Decouple สูง ดังนั้นจะ EJB ให้มาสร้าง Object โดยการ new แบบเดิมๆ คงจะไม่เข้าที ทาง EJB 2.0 ใช้วิธีนี้ครับ  (ผมเขียนเป็น Pseudo Code อิงตามภาษา C# นะครับ)

    ICar car = PortableRemoteObject.narrow(contextEnv.lookup("ejb/car"), ICar.class);

    ตัวนี้ใช้ Design Pattern ที่ชื่อว่า Factory Method เช่นเดียวกันกับข้างต้น แต่ภายในมีความซับซ้อนกว่ามาก โดยที่ ข้อมูลว่าจะเอา Object ไหนมาให้ จะอยู่ในฐานข้อมูลอีกตัว ที่ชื่อว่า JNDI Server ทั้งนี้เพื่อเพิ่มความยืดหยุ่นให้โปรแกรม คุณอยากเปลี่ยนชนิดของ Class ที่ new ก็ไปแก้ในฐานข้อมูลนอกโปรแกรม เช่นเปลี่ยน Algorithm ในการเข้ารหัส ไม่ต้อง Compile โปรแกรมนั้นใหม่ด้วยซ้ำ 

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

      ผมเคยทดลองใช้งาน EJB 2.0 เมื่อนานมาแล้ว ความรู้สึกแรกที่ใช้งานคือจุกครับ  ผมใช้เวลาสามวันถึงจะปล้ำมันขึ้นโปรแกรม Hello ได้ ดูอะไรมันก็ยุ่งยากไปหมด สร้าง Class มา Class หนึ่ง ต้อง Implement  กันหลาย Interfaces  ถ้าผมจำไม่ผิดนะครับ 7  Interfaces เลยทีเดียว แล้วยังต้องยุ่งกับ JNDI อีก เวลานั้น IDE ก็ยังไม่ค่อยเก่ง ทุกอย่างต้องทำมือหมด ผมเลยต้องใช้ ANT มาช่วย  เวลารันก็ช้า ทำงานค่อนข้างช้า ในเวลานั้น ผมเข้าใจว่าความสามารถผมคงไม่ถึง ใช้งานระดับ Enterprise แบบนี้ไม่ได้ ผมเคยเข้าไปฟังงานสัมนาทางฝั่ง Java ก็บ่อย ตอนนั้นถนนทุกสายมุ่งสู่ EJB ครับ ทุกคนเชียร์กันหมด ขอย้ำอีกทีครับ ว่าไม่ได้รักส้ม ตำหนิแอ๊ปเปิ้ล เพียงแค่อยากจะบอกถึงที่มาว่าทำไม่ถึงมี Unity วันนี้ มันต้องก้าวผ่านปัญหาเหล่านี้มาครับ

Spring Framework

    เวลานั้นผมยังไม่ยอมแพ้ครับ เราทำอะไรผิดหลักไปรึเปล่า มันน่าจะมีทางสายตรงสำหรับ EJB ที่ดีกว่า ผมเลยลองหาหนังสืออ่านดู ก็บังเอิญไปเจอหนังสือชื่อว่า "Expert one-on-one J2EE Design and Development" โดย Rod Johnson ชื่อมันเข้าทาง ผมเลย เอามาอ่านโดยหวังว่า จะรู้แนวทางที่พัฒนา Java Enterprise Edition ที่ถูกต้อง แต่พออ่านดูก็หงายหลังครับ หนังสือเล่มนี้เฉ่ง EJB เละเลย เข้าทำนองเขียนไปด่าไป มีคำพูดคำหนึ่งที่น่าสนใจ เขาบอกว่า EJB มันพยายามทำ "One size fits all"  ถ้าต้องการทำงานสลึงเดียว แต่ต้องแรงเท่ากันโครงการ 5 บาท  ไม่ว่างานเล็กงานใหญ่ ต้องยุ่งยากเท่ากับโครงการขนาดที่ใหญ่ที่สุด เขาว่าโปรเจคแค่เพียง 5% เท่านั้นถึงจำเป็นต้องมีความยุ่งยากขนาดนี้ ส่วนอีก 95% ที่ไม่ใหญ่ ก็ต้องรับกรรมไป โปรเจคจะตายเพราะความบวมนี่แหละครับ หลังจากหนังสือเล่มนี้ออกไป มีผลกระทบในวงกว้างมาก   จริงๆ แล้วผมว่าเวลามันพอดีกันต่างหาก คนใช้ EJB แล้วเกิดปัญหาก็มีเยอะ กระแสต่อต้าน EJB 2.x  ก็เยอะมากในเวลานั้น
    ต่อมา Rod Johnson ออกหนังสือเล่มที่ 2 เพื่อตอกย้ำ ผมไม่เคยอ่านครับ แต่ชื่อเรื่องบอกทุกอย่างครับ "Expert One-on-One J2EE Development without EJB" พอมาถึงเล่มที่ 3 ก็ถึงบางอ้อครับ ชื่อหนังสือ "Professional Java Development with the Spring Framework"  

    Rod Johnson บอกว่า Code ที่เราเขียนใน EJB Container นั้น แม้ว่าจะคุยว่าไม่ Coupling กับ Vendor แต่มันก็ Coupling อยู่กับ ตัว Container นั่นหมายถึง Class ที่สร้างสำหรับ EJB มันมีการเรียกใช้ PortableRemoteObject.narrow() ซึ่งเป็นของเฉพาะสำหรับ EJB เท่านั้น ถ้าไม่ใช้ EJB  Code นี้ก็เอาไปใช้ที่อื่นไม่ได้ Rod  Johnson เลยชูธงคำว่า "POJO" หรือ Plain Old Java Object  ซึ่งเรียบเรียงเป็นไทยง่ายๆ ว่า  Class ธรรมดานี่แหละ ไม่มีส่วนของ Container ปลอมปน ดังนั้นจึงสามารถเอาไปใช้นอก Container ได้ พอเป็น .NET ก็เรียกว่า Plain Old CLR Object (PONO) และคำนี้เองเป็นคำที่ขลัง Framework ต่างๆ ต้องมีคุณสมบัตินี้เป็นมาตรฐาน ถ้าทำแบบ EJB 2.x อีกคงไม่ได้รับการยอมรับแน่ เวลานั้นถนนทุกสายมุ่งสู่ POJO กันหมด อะไรไม่ใช่ POJO มาแบบ EJB 2.x ก็จะถูกปฏิเสธหมด กระแสแรงจริงๆ 

    ย้อนกลับมาที่ EJB  มันน่าเจ็บใจครับ  คนกลุ่มเดิมครับ ที่เคยเชียร์ EJB 2.x พอมาเป็น EJB 3.0 ก็เชียร์ใหญ่เช่นเดิม แต่กลับถล่ม EJB 2.x เองจนจมดิน เฉ่งเหมือน Rod Johnson เฉ่งนั่นแหละ ผมเองยังงง นิทานเรื่องนี้สอนให้รู้ว่า อย่าเชื่อใครง่ายๆ โดยเฉพาะอย่างยิ่งคนที่มีส่วนได้เสียกับเรื่องนั้น ผลประโยชน์มันทำให้แม้แต่ผีลุกมาช่วยโม่แป้งได้จริงๆ ครับ ต่อไปทำอะไร ฟังหูไว้หูครับ แต่ขอกล่าวตรงนี้เล็กน้อยครับ ว่านั่นเป็นเรื่องอดีต  ปัจจุบัน ตามข่าวว่า  EJB 3.0  เป็น POJO โดยสมบูรณ์แล้ว แต่ผมก็ไม่เคยคิดกลับไปใช้ครับ ใช้ Spring ดีกว่า

    กลับมาที่ Spring Framework ผู้คิดค้นก็ไม่ใช่ใครที่ไหนครับ ก็ Rod Johnson นั่นเอง แนวคิดในการออกแบบนั้นดูจะตรงข้ามกับ EJB 2.x แต่คงความสามารถสูสีกัน ที่ว่าตรงกันข้ามนั้น Spring Framework เน้นเฉพาะ Core ของ Container แบบ IoC เท่านั้น ส่วนความสามารถอื่นๆ นั้นเป็นส่วนขยายที่เรียกว่า Extensions ถ้าไม่ใช้ก็ไม่ต้องใส่เข้าไป ความซับซ้อนก็ลดฮวบเลยครับ แต่ถ้าอยากใช้ก็เพิ่มเข้าไปได้  มันไม่พยายามทำตัวเป็น "One Size Fits All"  แถมส่วนขยายนี้ยังเพิ่มได้เรื่อยๆ ด้วย Community ช่วยกันทั่วโลก ไม่เลวเลยครับ

    มีคน Port เอา Spring มาใช้งานบน .NET ถ้าสนใจก็ลองไปที่ http://www.springframework.net ดูครับเขาพัฒนากันมานานมากแล้ว Stable แล้ว มีให้ Download ไปใช้ฟรีๆ ครับ

Dependency Injection

    มาถึงเรื่องสุดท้ายก่อนจบบทความนี้ ก็เป็นเรื่องของ Spring Framework สร้าง Object อย่างไรหนอ ที่ได้ Loosely Coupling แถมยังเป็น POJO อีกต่างหาก เมื่อเป็น POJO จึงสร้างแบบธรรมดาแบบนี้ครับ คือ

class MyClass
{
    private ICar Car;

    public void process()
    {
        Car.Start();
        Car.Stop();
    }
}


    ถ้าสังเกต จะเห็นว่า Car ไม่มีการ new และไม่ได้ Init โดยวิธีการใด ใช้งานไม่ได้ครับ ดังนั้นเพื่อให้รองรับกับ Spring.NET หรือ Unity ได้ต้องปรับ Code เล็กน้อยครับ สร้างเป็น Property 

class MyClass
{
    public ICar Car {get; set;}

    public void process()
    {
        Car.Start();
        Car.Stop();
    }
}
 
    ปรับ Car ให้กลายเป็น Property ครับ เพื่อรองรับ Object ในอนาคต Class นี้ ก่อน Run ได้นั้น มันจะถูกฉีด Object ของ ICar ไม่รู้ว่าเป็น Toyota หรือ Honda มาจากภายนอก วิธีนี้ก็เป็น Pattern ตัวหนึ่งที่ชื่อว่า Dependency Injection คำนี้คิดโดย Martin Fowler เจ้าเก่าครับ มันเหมือนการฉีดยา ฉีด เอา Object เข้ามา เอามาใช้งานได้เลยครับ แบบนี้การ Coupling จะต่ำมาก จะ Coupling ใน ระดับ Interface เท่านั้น ไม่ Coupling กับ Class หรือ Object ใดๆ อีกอีก Design Patterns ที่ว่าด้วยการสร้าง Object หลาย Patterns อาจถูกทดแทนด้วย Dependency Injection + Inversion of  Control ได้ครับ
      ถ้า Class นี้เอาไปใช้นอก Container ก็แค่ new object ของ Car อยู่ข้างนอก แล้วคุณก็ฉีดแบบ Manual เองเข้ามาใน Property ก่อนการใช้งาน เท่านี้ก็ใช้งานได้ทั้งใน Container และนอก Container และใช้ได้กับ หลาย Project ด้วย มีการ Reuse ที่สูง

    แล้วถ้าใครสงสัยว่า จะรู้ได้อย่างไรว่า จะ Inject Object ตัวไหน เราจะกำหนดรายละเอียดในแฟ้ม XML ครับ วันนี้โควต้าหมด เอาไว้ต่อคราวหน้าดีกว่าครับ

ทิ้งท้าย

    บทความนี้ผมปูพื้นถึงที่มาที่ไปของ Unity บทความหน้า ผมจะแสดงตัวอย่างการใช้งาน Unity ซึ่งคล้ายกับ Spring.NET มาก โปรดติดตามตอนต่อไป

สุพจน์

02/FEB/09

ร่วมแสดงความคิดเห็น