Assembly #1: The Evolution

    เรื่องนี้เป็นเรื่องสืบเนื่องมาจากเรื่องของ NameSpace และอีกเช่นเคยครับที่มีคน email มาถามผมเรื่องเกี่ยวกับ Versioning ที่ผมเขียนไปในเรื่องของ Interface Inheritance ทำไมถึงไม่เห็นเหมือนกับ Versioning ที่อยู่ใน Reference Manual ของ C# ผมเลยได้โอกาสเขียนเรื่องนี้ให้อ่านกันครับ

    เรื่องที่ C# ทำ Versioning นั้นเป็นเรื่องของการใช้คำสั่ง new แทนคำสั่ง override ซึ่งผมไม่เห็นประโยชน์ของมันเท่าไหร่ เลยไม่ได้เขียนให้อ่านกัน ส่วนเรื่อง Versioning ในเรื่อง Interface Inheritance นั้นมันเป็นคนละเรื่องครับ ซึ่งเรื่องหลังนี้มีความสัมพันธ์กับ Assembly อย่างใกล้ชิด วันนี้เราจะคุยกันเรื่องนี้ครับ

    Assembly เป็นศัพท์เฉพาะที่ Microsoft สร้างขึ้น (อีกแล้ว) ถ้าพูดเป็นกันเป็นภาษาชาวบ้านก็อาจจะพูดได้ว่า แท้ที่จริงแล้ว Assembly ตามความหมายของ .NET นั้นก็คือพวกแฟ้ม .dll รุ่นใหม่นั่นเอง เรามาลองดูประวัติกันหน่อยดีกว่าว่าทำไมต้องมี Assembly และ .dll ที่ใช้กันอยู่ทุกวันนี้มีปัญหาอะไรบ้าง

เริ่มกันที่ DOS

    ย้อนยุคไปไกลเลยครับ ไปถึง DOS ยุคสมัย DOS นั้นโปรแกรมยังไม่ใหญ่มาก โปรแกรมส่วนใหญ่ก็จะไม่มี Graphic มีแต่ตัวหนังสือ (ยกเว้นเกมส์) การแสดงตัวอักษรต่างๆ บนหน้าจอหรือการติดต่อกับอุปกรณ์ต่างๆ เช่น Harddisk, floopy disk นั้นบน DOS และ BIOS ได้เตรียมฟังก์ชันการใช้งานให้เราสามารถเรียกใช้งานได้อยู่แล้ว และถึงแม้ว่าเราจะไม่ใช้ฟังก์ชันดังกล่าว เราเขียนติดต่อกับ I/O โดยตรงก็ทำได้โดยง่าย และขนาดของโปรแกรมไม่ใหญ่

    ถ้าเรามองมุมมองของการเขียนโปรแกรม โปรแกรมที่เป็น .exe ส่วนมากบน DOS นั้นสร้างมาจากภาษา C ซึ่งแน่นอนครับว่าเกือบทุกโปรแกรมต้องมีการเรียกใช้ฟังก์ชันที่ชื่อว่า printf() และ้ถ้าเรามีโปรแกรม .exe อยู่ 1,000 ตัวนั่นก็หมายความว่าเรามี code ของ printf() แทรกอยู่ทั้ง 1,000 โปรแกรม

มาถึง Windows 16 bits

    Windows รุ่นเปลี่ยนแปลงโลก นั่นก็คือ Windows 3.1 ซึ่ง Windows นั้นเป็น OS ที่ใช้ Graphic User Interface ซึ่งเลียนแบบมาจาก Apple McIntosh สิ่งที่เปลี่ยนไปก็คือ โปรแกรมต่างๆ นั้นแสดงผลเป็น Graphic ทั้งหมด และการเปลี่ยนแปลงครั้งนั้นสร้างความได้เปรียบหลายอย่างให้กับ Microsoft, เช่น Microsoft Word สามารถล้ม Word Perfect, Microsoft Excel ล้ม Lotus 123, Access ล้ม Xbase, และเครื่องมือในการเขียนโปรแกรมนั้น Microsoft สามารถล้ม ตระกูล Turbo ของ Borland เป็นต้น ชื่อโปรแกรมที่กล่าวมาข้างต้นล้วนแล้วแต่เคยผูกขาดทั้งตลาด แต่เมื่อ Microsoft เปลี่ยน OS ให้กลายเป็น Graphics ทำให้บริษัทต่างๆ ดังกล่าวตั้งตัวไม่ทันจนเสียการผูกขาดดังกล่าวไปทั้งหมด แล้วคุณว่าเหตุการณ์แบบนี้มันจะเกิดขึ้นอีกครั้งกับ .NET หรือไม่?

    เรามามองถึงมุมมองคนออกแบบ Windows รุ่นแรกๆ กันหน่อยดีกว่า ในยุคนั้น Harddisk มีขนาดเล็กมาก Memory ก็น้อย ความเร็วของ CPU ก็จำกัด ทุกสิ่งทุกอย่างดูเหมือนว่ายังไม่พร้อมสำหรับ Windows ครับ ดังนั้นการออกแบบ Windows ในยุคนั้นจึงถือเอาหลักประหยัด Resource ให้มากที่สุดเท่าที่จะเป็นไปได้ ดังนั้นสิ่งที่ Micorosoft นำเอามาใช้ในเวลานั้นก็คือสิ่งที่เรียกว่า Shared Library คือการที่เอา Library ที่มีการใช้ร่วมกัน (เช่น printf()) เอาไว้ในแฟ้มข้อมูลแยกต่างหาก จะไม่รวมเข้าไปอยู่ใน .exe ดังนั้นถ้าโปรแกรม 1,000 ตัว มีการเรียกใช้ printf() จะไม่มีโปรแกรมตัวไหนเลยที่เก็บ code ของ printf() เวลารันโปรแกรม จะมีการดึงเอา code ของ printf() มาใช้ทำให้โปรแกรมแต่ละตัวมีขนาดเล็กลงมากจนน่าแปลกใจ โปรแกรมที่พิมพ์คำว่า Hello, World รุ่นบน DOS และบน Windows นั้นมีขนาดแทบไม่แตกต่างกัน ถ้าไม่มีเรื่อง Shared Library มาช่วย โปรแกรม Hello, World บน Windows อาจจะใหญ่กว่ารุ่นบน DOS เป็นหลายร้อยเท่าครับ

    และจุดที่มีการประชาสัมพันธ์กันค่อนข้างจะมากสำหรับ Shared Library ก็คือความดีที่สามารถแก้บั๊กได้ เช่นถ้า printf() มีบั๊ก เราไม่จำเป็นต้องหาทั้ง 1,000 โปรแกรมมาใหม่ ในเมื่อโปรแกรมแต่ละตัวเรียกใช้ printf() ข้างนอก เราเพียงปรับปรุง Shared Library ของ printf() เท่านี้นโปรแกรมทุกตัวก็ถือได้ว่ามีการแก้บั๊กแล้วทั้งหมด

    และ Shared Library ที่กล่าวมา จะอยู่ในแฟ้มข้อมูลที่เรารู้จักกันดี นั่นก็คือ .DLL นั่นเอง (Dynamic Linked Library)

Windows 95 กำเนิด COM Component

    มายุค Windows 95 .dll ซึ่งเคยเป็นพระเอกนั้น ถูกมองเป็นผู้ร้ายไปครับ จนกระทั่งทุกวันนี้ มีผู้คนเรียก .dll กันติดปากว่า DLL Hell, เรามาดูกันว่าทำไมถึงเป็นอย่างนั้น

    ปัญหาหลักที่เกิดขึ้นกับ .DLL นั้นก็คือมันเป็นสิ่งที่ใช้ร่วมกันกันหลายโปรแกรม ทำให้เกิดปัญหาดังนี้ครับ

 

    ทาง Microsoft จึงได้ออกแบบ .DLL แบบใหม่ขึ้นครับ ซึ่งผมเรียกเอาเองว่าเป็น Version 2 ซึ่งเรารู้จักกันในชื่อ COM Component  มันเป็นความพยายามที่จะแก้ปัญหา DLL Hell โดยที่ COM Component นั้นสามารถรองรับ Interface Inheritance ทำให้ .DLL ตัวเดียวกันสามารถมีหลาย Version ซึ่งเรื่องราวการทำ Versioning แบบนี้ ดูได้จาก Interface Inheritance : Versioning ครับ

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

Windows 98SE

    ปัญหา DLL Hell เริ่มเลวร้ายขึ้น เพราะจำนวนโปรแกรมที่มีการพัฒนาขึ้นสำหรับ Windows นั้นมีปริมาณเพิ่มขึ้นแบบทวีคูณ ทำให้ Windows นั้นถือว่าเป็น OS ที่ไม่ Stable เมื่อเทียบทางค่าย UNIX เช่น Linux เป็นต้น แต่ถ้าไล่กันเข้าไปจริงๆ ปัญหาก็เกิดจาก DLL Hell นั่นเอง

    มีการเปรียบเทียบ DLL Hell กับ "Achilles's Heel" ผมของอธิบายถึงที่มาก่อนก็แล้วกันครับ ในมหากาพย์ อีเลียต นั้นมีวีรบุรษสงครามที่ชื่อว่า Achilles ในตอนเด็กนั้น แม่นำตัวไปจุ่มแม่น้ำ Styx ทำให้บริเวณที่ถูกน้ำทิพย์นั้นคงกระพันครับ แต่มีที่เดียวเท่านั้นครับที่ไม่โดนน้ำทิพย์นั้นก็คือที่ข้อเท้า เพราะเป็นบริเวณที่มือของแม่นั้นใช้จับ Achilles จุ่มครับ และในสงคราม Achilles แสดงให้โลกเห็นว่าเป็นนักรบที่เก่งที่สุด แต่สุดท้ายความลับถูกเปิดเผยทำให้ถูกธนูยิงเข้าไปที่ข้อเท้าจนถึงแก่ความตายครับ

    Microsoft ไม่นิ่งนอนใจครับอุตส่าห์ลงทุนลงแรงมากที่สุดเท่าที่เคยมีมา แต่กลับไปตายน้ำตื้นแบบนี้ ทาง Microsoft จึงประกาศโครงการที่ชื่อว่า Fusion Technology เพื่อแก้ไขปัญหา DLL Hell โดยเฉพาะครับ และ Windows 98SE นั้นถือว่าเป็นรุ่นแรกของ Technology นี้ครับ Microsoft ทำดังนี้ครับ

    เมื่อเวลา Install Programming นั้น ถ้าพบว่า .DLL ที่กำลัง Install นั้นชนกับ DLL ที่มีอยู่แล้ว ทาง Windows จะแจ้งโปรแกรมที่กำลัง Install ว่าได้ย้าย .DLL ที่กำลัง Install นั้นไปอยู่ที่อื่น ทำให้ไม่ต้องทับกัน ซึ่งการย้ายแบบนี้เราเรียกว่า Side-by-Side และ Technology ที่ใช้ในรุ่นนี้มี Code Name ว่า Hydrogen

    แต่มันก็แทบไม่ได้ช่วยอะไรครับ เพราะโปรแกรมที่กำลัง Install นั้นต้องเรียกใช้ API พิเศษ ซึ่งมีเพียงโปรแกรมไม่กี่ตัวครับที่ใช้ประโยชน์จากมัน

Windows ME / 2000

    Fusion Technology รุ่นต่อมาคือ Windows ME / 2000 ซึ่งมีสิ่งที่เรียกว่า Windows File Protection (WFP) หรือ System File Protection (SFP) ซึ่งทำการป้องกันไม่ให้ System Files ที่สำคัญถูกโปรแกรมใดๆ ทับ ถ้าถูกทับจริงๆ ก็จะมีกรรมวิธีในการ Restore เพื่อรักษาให้ระบบเสถียร แต่นั้นก็สามารถป้องกันได้เฉพาะ System Files ไม่รวมถึง Application ทั่วไป

.NET กับ Fusion Technology 2.0

    เมื่อมาถึง .NET ซึ่งเป็นยุคที่กำลังเครื่องของคอมพิวเตอร์และ Resource ต่างๆ เริ่มมีมากขึ้น Harddisk ขนาด 20 GB ที่ใช้ตามบ้านถือว่ามีขนาดเล็ก ซึ่งถ้าเปรียบเทียบกับก่อนหน้านั้นประมาณ 10 ปี ขนาด Harddisk 20GB นั้นถือว่าเป็นศูยน์คอมพิวเตอร์ขนาดยักษ์เลยทีเดียว

    เมื่อกำลังเครื่องของคอมพิวเตอร์ไม่ใช่เป็นข้อจำกัด ดังนั้นแนวทางของ Fusion Technology นั้นจึงออกไปในแนวทางที่ไม่มีการทับกัน รุ่นต่างๆ ให้ถือว่าเป็นคนละแฟ้มข้อมูลกัน เิริ่มต้น .NET นั้นทำการออกแบบ .DLL เสียใหม่ ซึ่งผมขอเรียกว่าเป็น Version 3 ซึ่งในรุ่นนี้จะมีสิ่งที่เก็บนอกจากตัว Code แล้วนั่นก็คือสิ่งที่เรียกว่า MetaData ซึ่งเป็นการอธิบายตัว .DLL ว่าภายในนั้นประกอบด้วยอะไรบ้าง เราถือว่า MetaData นั้นเป็นข้อมูลที่สำคัญ ที่สามารถนำไปใช้สร้าง IntelliSense ให้กับ Visual Studio ได้ และยิ่งไปกว่านั้น MetaData ยังเก็บ Version ของ .DLL นั้นด้วย และ .DLL รุ่นใหม่นี่เองที่ Microsoft เรียกว่า Assembly

    วันนี้ผมยังไม่เจาะลึกถึงเนื้อหาของ Assembly ผมขอคุยถึง Fusion Technology 2.0 ที่มากับ .NET ก่อนว่ามันสามารถแก้ปัญหา DLL Hell ได้อย่างไร

    เริ่มต้นครับ คือ Assembly มี 2 ประเภท แบบแรกคือที่เป็น Private มันจะอยู่เฉพาะกับโปรแกรมของเราจะไม่ไปรบกวนกับโปรแกรมอื่น และอีกแบบคือ Shared ซึ่งมันต้องไปอยู่ใน Directory ที่ใช้ร่วมกันระหว่างโปรแกรม ในบทนี้ผมจะเน้นอย่างหลังเท่านั้นครับ

    Assembly ที่เป็นแบบ Shared นั้น จะเก็บอยู่ในส่วนที่เรียกว่า Global Assembly Cache (GAC) ซึ่งโดยปกติแล้วจะอยู่ใน WINNT\Assembly\GAC  โดยที่การที่ไม่ให้โปรแกรมทับกันนั้น ทาง Micorosft ใช้หลักการเข้ารหัสแบบ RSA โดยที่กำหนดให้บริษัททุกบริษัทที่จะนำเอา Assembly ไปเก็บไว้ใน GAC ได้นั้นต้องสร้าง Key 2 ตัว นั่นก็คือ Public Key และ Private Key  ทาง Microsoft จะนำเอา 8 bytes หลังของ Public key ของบริษัทนั้นมาสร้างเป็นชื่อ Directory เช่น 1.0.2411.0__b77a5c561934e089  ส่วนแรก 1.0.2411.0 คือ Version และส่วนที่สอง b77a5c561934e089 นั้นเป็น 8 bytes สุดท้ายของ Public key ของ Microsoft ด้วยวิธีนี้จะมีมีการทับกันเกิดขึ้นครับ ชื่อ Directory แบบพิเศษนี้ Microsoft เรียกว่า Strong Name ครับ (โปรแกรมที่ใช้ในการจัดการ GAC ชื่อว่า GACUtil.exe มามาให้กับ .NET Framework ครับ)

    การนำ RSA มาใช้นั้นยังส่งผลถึงเรื่อง Security อีกด้วยครับกล่าวคือมันสามารถพิสูจน์ทราบได้ว่า Assembly ตัวนี้ที่กำลังจะลงนั้น มาจากบริษัทนั้นๆ จริงหรือไม่ จะไม่มี Hacker คนไหนสวมรอยแอบเอาโทรจันใส่เข้ามา ในอดีตนั้นเราไม่มีทางรู้ได้เลย แต่ .NET ใช้ Technology ที่ชื่อว่า Digital Signature ทุก Assembly จะมีลายเซ็นต์อยู่ ถ้ามีการเปลี่ยนแปลงใดๆ แม้แต่นิดเดียวมันจะทำให้ลายเซ็นต์ตัวนั้นพัง เราจะรู้ได้เลยว่า Assembly ดังกล่าวมีปัญหา ลายเซ็นต์ตัวนี้ปลอมได้ยากมากครับ ซึ่งถ้าใครสนใจเรื่องนี้ ลองไปศึกษาเกี่ยวกับคณิตศาสตร์ที่เกี่ยวกับเรื่อง Number Theory หรือถ้าเป็นคอมพิวเตอร์ก็ทางด้าน Cryptography ลองไปหาอ่านดูครับ มันนอกเรื่องที่ผมจะนำเสนอครับ

Windows XP - Fusion Technology 2.5 การสิ้นสุดของ DLL Hell

    เราจะเห็นได้ว่าโปรแกรมในอนาคตที่สร้างจาก .NET นั้นจะไม่มีปัญหาเรื่อง DLL Hell อีกต่อไป ทั้งนี้ก็เนื่องจากการใช้งานของ Fusion Technology 2.0 แต่ปัญหา DLL Hell นั้นใช่จะจบสิ้นเลยทีเดียว เรายังมี .DLL version 2 หรือ COM Component ที่ Fusion Technology 2.0 ยังไม่รองรับ เนื่องจากใน COM Component นั้นไม่มี Meta Data ที่ Fusion Technology จะนำเอาไปสร้าง Strong Name ได้ (ส่วน DLL version 1 ที่เป็น 16 bits นั้นคงไม่ต้องกังวลมาก เพราะจำนวนโปรแกรมที่น้อยอยู่แล้ว และมันไม่สมควรที่จะรันโปรแกรมเ่ก่าแบบนั้นครับ)

    ทาง Microsoft มีโครงการ Fusion Technology 2.5 ที่จะมากลับ Windows XP พร้อมกับคุยไว้ว่า version 2.5 นี้คือจุดสิ้นสุดของ DLL Hell โดยถาวร โดยความสามารถที่จะจัดการกับ COM Component เก่าๆ ได้ด้วย ซึ่งผมยังไม่ได้รายละเอียดของเรื่องนี้ครับ ถ้ามีเมื่อไหร่จะเอามา Update ที่หน้านี้ครับ