Ada, ภาษาที่สร้างทั้งการออกแบบและตัวภาษา
(iqiipi.com)- Ada ถือกำเนิดขึ้นท่ามกลางความโกลาหลด้านซอฟต์แวร์ของกระทรวงกลาโหมสหรัฐในทศวรรษ 1970 โดยเป็นภาษาที่มี ระบบชนิดแบบสถิตที่เข้มงวดและการแยกสเปกออกจากการอิมพลีเมนต์ เป็นหัวใจสำคัญ
- ด้วย โครงสร้างแพ็กเกจและการซ่อนรายละเอียดเชิงตัวแทน ทำให้เกิดการห่อหุ้มอย่างสมบูรณ์ และต่อมามีอิทธิพลต่อระบบโมดูลของภาษาแบบใหม่อย่าง Java, C#, Go เป็นต้น
- ชนิดที่มีข้อจำกัดเชิงความหมาย, generic, concurrency (task), การออกแบบบนฐานสัญญา ล้วนเป็นแนวคิดที่ Ada นำเสนอไว้ล่วงหน้าหลายสิบปี และถูกสืบทอดต่อโดย Haskell, Rust, Swift เป็นต้น
- SPARK Ada ใช้การพิสูจน์เชิงรูปนัยเพื่อตัดทั้ง data race และข้อผิดพลาดเชิงตรรกะออกไป จึงถูกใช้งานในสาขาที่ต้องการความเชื่อถือสูงอย่าง การบิน รถไฟ และระบบป้องกันประเทศ
- แม้ Ada จะไม่ใช่ภาษายอดนิยมในวงกว้าง แต่ในฐานะ “ภาษาที่ทำงานได้ถูกต้องอย่างเงียบ ๆ” มันคือรากฐานที่เสนอหลักการพื้นฐานของการออกแบบภาษาโปรแกรมสมัยใหม่
ภูมิหลังการกำเนิดและปรัชญาการออกแบบของ Ada
- ช่วงต้นทศวรรษ 1970 กระทรวงกลาโหมสหรัฐ (DoD) สำรวจพบว่าสถานการณ์ในระบบอาวุธ โลจิสติกส์ และการสื่อสาร มีภาษากับภาษาถิ่นปะปนกันมากกว่า 450 แบบ
- แต่ละระบบมีปัญหาใช้งานร่วมกันไม่ได้ บำรุงรักษาไม่ได้ และผู้เขียนดั้งเดิมไม่อยู่แล้ว
- ส่งผลให้เกิด วิกฤตการจัดหาซอฟต์แวร์
- DoD ไม่เลือกใช้ภาษาที่มีอยู่เดิมอย่าง COBOL, Fortran, PL/1 แต่ใช้เวลานาน 5 ปีในการกำหนดความต้องการ
- เอกสารพัฒนาจาก Strawman → Woodenman → Tinman → Ironman → Steelman
- Steelman (1978) กำหนดให้ต้องมีการแยกอินเทอร์เฟซอย่างชัดเจน ระบบชนิดแบบสถิตที่เข้มงวด concurrency ในตัว การจัดการข้อยกเว้นที่สอดคล้องกัน ความเป็นอิสระจากเครื่อง ความอ่านง่าย และความสามารถในการตรวจพิสูจน์
- ในการแข่งขันระหว่าง 4 ทีม (Green, Red, Blue, Yellow) เมื่อปี 1979 ทีม Green ที่นำโดย Jean Ichbiah ได้รับเลือก และภาษาถูกตั้งชื่อว่า Ada
- ชื่อนี้ตั้งขึ้นเพื่อยกย่อง Ada Lovelace และสื่อถึงเจตนารมณ์ของภาษา
โครงสร้างแพ็กเกจและการห่อหุ้ม
- โครงสร้างศูนย์กลางของ Ada คือ แพ็กเกจ (package) โดยแยก specification และ body ออกจากกันในเชิงกายภาพ
- specification คือสัญญาที่เปิดเผยต่อภายนอก ส่วน body คือการอิมพลีเมนต์ และคอมไพเลอร์จะบังคับความสัมพันธ์ระหว่างทั้งสอง
- โค้ดฝั่งไคลเอนต์ไม่สามารถเข้าถึงองค์ประกอบที่ไม่ได้อยู่ใน specification ได้
- โครงสร้างนี้เป็น ต้นแบบของระบบโมดูล ซึ่งภาษาต่อมาหลายภาษาได้เลียนแบบเพียงบางส่วน
- Java, Python, JavaScript, C, Go, Rust ล้วนยังไม่สามารถทำการแยกเชิงโครงสร้างได้สมบูรณ์แบบเท่า Ada
- private type เปิดเผยเพียงชื่อ แต่ซ่อนรูปแบบการแทนค่าภายในไว้อย่างสมบูรณ์
- ไคลเอนต์ไม่อาจรู้โครงสร้างภายในของชนิดนั้น และใช้ได้เฉพาะปฏิบัติการที่อนุญาตเท่านั้น
- สิ่งนี้เป็น การซ่อนรายละเอียดเชิงตัวแทน (representational invisibility) ที่แข็งแกร่งกว่า access control แบบ
privateของ Java
- Java และ C# ค่อย ๆ พัฒนาไปสู่ระดับการห่อหุ้มแบบ Ada ตลอดหลายสิบปี
ระบบชนิดและข้อจำกัดเชิงความหมาย
- Ada นิยาม ความแตกต่างระหว่าง type และ subtype ในความหมายเชิงคณิตศาสตร์
- ตัวอย่าง:
type Age is range 0 .. 150คือการสร้างชนิดแยกต่างหากที่มีข้อจำกัดด้านช่วงค่า - การส่งค่าระหว่างชนิดที่ไม่ถูกต้องจะถูกตรวจพบเป็น ข้อผิดพลาดตอนคอมไพล์
- ตัวอย่าง:
- สำหรับปี 1983 ระบบชนิดของ Ada มีพลังในการแสดงความหมายสูงกว่า C, Fortran, Pascal มาก
- โดยใช้ ชนิดที่มีข้อจำกัดเชิงความหมาย เพื่อป้องกันข้อผิดพลาดระดับโดเมน
- discriminated record คือโครงสร้างที่มีฟิลด์ต่างกันตามค่าที่กำหนด
- สิ่งนี้เทียบเท่ากับ sum type หรือ algebraic data type (ADT) ในภาษาสมัยใหม่
- Haskell, Rust, Swift, Kotlin, TypeScript และภาษาอื่น ๆ นำแนวคิดเดียวกันนี้มาใช้ในอีกหลายสิบปีต่อมา
Generic และความเป็นพหุรูป
- generic ของ Ada เป็นหน่วยที่รับชนิด ค่า ซับโปรแกรม และแพ็กเกจเป็นพารามิเตอร์
- เป็นการทำ พหุรูปแบบสถิต (parametric polymorphism) ที่ตรวจสอบชนิดในเวลาคอมไพล์
- C++ (1990), Java (2004), C# (2005), Go (2022) ต่างค่อย ๆ เพิ่มความสามารถคล้ายกันหลัง Ada อีกหลายสิบปี
- Java ใช้ type erasure ทำให้ข้อมูลชนิดสูญหายไปในรันไทม์
- Ada รองรับทั้งการคงข้อมูลชนิดในรันไทม์และ การทำแพ็กเกจให้เป็นพารามิเตอร์
- generic ของ Ada ให้พลังการแสดงออกในระดับ higher-kinded polymorphism
- มีแนวคิดใกล้เคียงกับ type class ของ Haskell, trait ของ Rust และ concepts ของ C++20
โมเดล concurrency และความปลอดภัย
- Ada มี concurrency ระดับภาษา (task) ติดมาในตัวตั้งแต่ปี 1983
- ผ่านการประกาศ
taskและโมเดลการสื่อสารแบบ rendezvous ทำให้เกิด การส่งข้อความโดยไม่มีสถานะที่ใช้ร่วมกัน - channel ของ Go ก็อยู่ในสายแนวคิดเดียวกันของ CSP (Communicating Sequential Processes)
- ผ่านการประกาศ
- Ada 95 เพิ่ม protected object เข้ามา
- ใช้ปกป้องการเข้าถึงข้อมูล และแยกเป็น
procedure,function,entry - ให้ทั้ง เงื่อนไข barrier อัตโนมัติ และ การซิงโครไนซ์แบบไม่ใช้ lock
- ใช้ปกป้องการเข้าถึงข้อมูล และแยกเป็น
- SPARK Ada ใช้การพิสูจน์เชิงรูปนัยเพื่อพิสูจน์ทางคณิตศาสตร์ว่าไม่มี data race, exception, range error และการละเมิด precondition/postcondition
- ขณะที่ borrow checker ของ Rust รับประกันเพียงความปลอดภัยด้านหน่วยความจำ SPARK สามารถ พิสูจน์ความสอดคล้องเชิงตรรกะได้ด้วย
การออกแบบบนฐานสัญญาและความปลอดภัยจาก null
- Ada 2012 รวม สัญญา (contracts) เข้ามาไว้ในภาษา
- สามารถระบุ precondition, postcondition และ type invariant ได้
- ชุดเครื่องมือของ SPARK นำสิ่งเหล่านี้ไปใช้ในการพิสูจน์แบบสถิต
- เป็นการทำให้แนวคิด Design by Contract ของ Eiffel (1986) เป็นรูปธรรมในระดับภาษา
- ขณะที่ C++, Java, Python, Rust ยังอยู่เพียงในระดับบางส่วนหรือผ่านไลบรารี
- Ada 2005 เพิ่มชนิด
not nullเพื่อรองรับ การตัด null ออกตั้งแต่ตอนคอมไพล์- โดยค่าปริยายจะรับประกันการล้มเหลวอย่างปลอดภัยผ่าน runtime exception (
Constraint_Error) - เป็นแนวทางที่คล้ายกับ nullable reference ใน C# 8.0
- โดยค่าปริยายจะรับประกันการล้มเหลวอย่างปลอดภัยผ่าน runtime exception (
โครงสร้างการจัดการข้อยกเว้น
- Ada 83 เป็นภาษาแรกที่นำ structured exception handling มาใช้
- exception ต้องประกาศก่อนใช้งาน ถูกจัดการตามขอบเขต และมีกฎการแพร่กระจายที่ชัดเจน
- checked exception ของ Java เป็นรูปแบบที่ต่อยอดจาก Ada โดยผู้เรียกต้องระบุข้อยกเว้นให้ชัดเจน
- ส่วน Ada อนุญาตให้มีการแพร่กระจาย exception ได้อย่างอิสระ
- Rust ตัด exception ออกไปและใช้ การจัดการข้อผิดพลาดบนฐาน
Resulttype- สิ่งที่ Ada มีส่วนสำคัญคือการทำให้การแพร่กระจาย exception มีโครงสร้างและคาดการณ์ได้
Annex และโครงสร้างการทำให้เป็นมาตรฐาน
- มาตรฐานของ Ada มีโครงสร้างส่วนขยายแบบเลือกใช้ที่เรียกว่า Annex
- Annex C~H นิยามความสามารถสำหรับงานระบบ งานเรียลไทม์ งานกระจาย งานเชิงตัวเลข และงานความเชื่อถือสูง
- คอมไพเลอร์ต้องได้รับ การรับรองแยกตาม Annex
- มีการตรวจสอบความสอดคล้องตามมาตรฐานผ่าน ACATS test ของ ACAA
- โครงสร้างมาตรฐานของ Ada สามารถนำไปใช้กับ การรับรองซอฟต์แวร์การบิน DO-178C ได้โดยตรง
- แม้ C/C++ ก็สามารถรับรองแบบเดียวกันได้ แต่ Ada เหมาะสมกว่าในเชิงโครงสร้าง
อิทธิพลของ Ada และความไม่สมดุลในการรับรู้
- Ada เป็น ภาษาที่ขับเคลื่อนโดยภาครัฐ จึงไม่ค่อยได้รับความสนใจในวัฒนธรรมสายซิลิคอนแวลลีย์
- ซึ่งนิยมไวยากรณ์กระชับแบบตระกูล C มากกว่า
- กรณีความสำเร็จของ Ada (ระบบการบิน รถไฟ ระบบป้องกันประเทศ) มี การมองเห็นต่ำเพราะไม่มีความล้มเหลว
- ระบบที่เชื่อถือได้สูงมักไม่ก่อให้เกิดประเด็นถกเถียงหรือเหตุการณ์
- ทิศทางการพัฒนาของภาษาสมัยใหม่กำลังค่อย ๆ มาบรรจบกับหลักการที่ Ada เสนอไว้แล้ว
- เช่น การแยกสเปกกับการอิมพลีเมนต์, การตรวจสอบชนิดแบบสถิต, concurrency ระดับภาษา, ความปลอดภัยบนฐานสัญญา
- ปัจจุบัน Ada ยังคงใช้งานอยู่ในระบบที่ต้องการความเชื่อถือสูง เช่น เครื่องบิน รถไฟ และยานอวกาศ และยังคงเป็น “ภาษาที่ทำงานได้ถูกต้องอย่างเงียบ ๆ”
1 ความคิดเห็น
ความเห็นจาก Hacker News
ฉันชอบ Ada มาก แต่พอพูดถึงระบบจัดการชนิดข้อมูลแล้วกลับไม่พูดถึง ภาษาในตระกูล ML (ML, SML, CML, Caml, OCaml ฯลฯ) เลยก็น่าแปลก
ภาษาเหล่านี้รองรับ structural typing ในระดับคอมไพเลอร์ตั้งแต่แรก ปัญหาของ Ada คือภาษาตัวมันเองใหญ่เกินไปและไวยากรณ์ซับซ้อน เหมือน PL/I, PHP, Perl ในบทความมองว่านี่เป็นข้อดี แต่ส่วนตัวคิดว่าส่วนขยายมาตรฐานที่แยกเป็น Annex นั้นยอดเยี่ยมกว่า ถ้าทำให้แกนหลักของภาษามีขนาดเล็กลงแล้วเน้น Annex เป็นศูนย์กลาง ก็น่าจะถูกใช้อย่างแพร่หลายกว่านี้
หนึ่งในเหตุผลที่ Ada ไม่ได้รับความนิยมคือ ราคาคอมไพเลอร์ สูงถึงหลายหมื่นดอลลาร์ ในยุคที่ยังไม่มีคอมไพเลอร์ฟรีหรือโอเพนซอร์ส ภาษาอื่น ๆ ใช้ได้ฟรี นั่นเป็นปัจจัยชี้ขาด
ตอนอ่านบทความ ฉันรู้สึกว่าทั้ง Ada และตัวบทความเองน่าสนใจมาก แต่ก็เห็น ข้อผิดพลาดด้านข้อเท็จจริง บางจุด เช่น บทความบอกว่ามีแค่ Ada ที่แยก implementation กับ specification ได้อย่างสมบูรณ์ ทั้งที่ JavaScript ก็สามารถนิยามองค์ประกอบ private ใน ES6 module ได้ คำอธิบายเรื่อง visibility ของ
privateใน Java ก็ผิดเช่นกัน ความผิดพลาดพวกนี้ทำให้ความน่าเชื่อถือของบทความลดลงprivateไว้ ภายนอกจะไม่สามารถเข้าถึงฟิลด์ภายในได้ แต่ใน JavaScript วัตถุใด ๆ ก็ยังเพิ่มหรือลบพร็อพเพอร์ตีได้อย่างอิสระ ดังนั้นระดับ การป้องกันตอนคอมไพล์ ของ Ada จึงเทียบกับ JS ไม่ได้เลยsetAccessible(true)เพื่อแก้ไขภายในของ String ได้ด้วยโดยรวมบทความดี แต่ประโยคแนว “ภาษา X เพิ่งมีฟีเจอร์นี้ช้ากว่า Ada” ที่วนซ้ำไปมาเริ่มน่าเบื่อ ถ้ามี ตัวอย่างโค้ด น่าจะโน้มน้าวได้ดีกว่านี้มาก
บัญชี Twitter นี้ ถูกสร้างในเดือนเมษายน 2026 และไม่ได้ระบุผู้เขียนไว้ มันสร้างผลงานได้มหาศาลในช่วงเวลาสั้น ๆ เลยทำให้การไม่เปิดเผยชื่อยิ่งน่าสนใจ
คำกล่าวที่ว่า “ทุกภาษาเพิ่งเพิ่ม sum type เข้ามาในช่วง 20 ปีที่ผ่านมา แต่ Ada มีมาตั้งแต่แรก” นั้นจริง แต่ต้นกำเนิดไม่ได้มาจาก Ada เพราะ ภาษา Hope หรือ NPL มีมาก่อน
UNIONและต่อมาแนวคิดนี้ก็พัฒนาต่อใน ALGOL 68, Hope, Miranda ฯลฯ ส่วนunionของ C ไม่ใช่แนวคิดเดียวกันฉันชอบบทความนี้มากจนหวังว่ามันจะไม่ได้เขียนโดย AI แต่ความเร็วในการโพสต์บน Twitter มันเร็วผิดปกติจนอดสงสัยไม่ได้
เดิมที USAF ตั้งใจจะใช้ Ada แต่เพราะการพัฒนาล่าช้าจึงไปใช้ JOVIAL แทน ฉันทำโปรเจกต์แรกด้วย JOVIAL ในปี 1981 และตอนนั้น Ada ยังอยู่ในขั้นข้อกำหนดเท่านั้น
ที่หน้าแรกของเว็บมีข้อความว่า “นี่ไม่ใช่จุดยืน แต่เป็นข้อเสนอ” แล้วมีคนเอาไปใช้เป็นหลักฐานว่าเป็น เว็บไซต์ที่ AI เขียน
ในบทความบอกว่า “ระบบโมดูลของ JavaScript ซ่อนการแทนค่าภายในของชนิดข้อมูลแบบ Ada ไม่ได้” แต่จริง ๆ แล้วใน JS ถ้าไม่ export ก็ซ่อนได้เพียงพอ เลยทำให้สงสัยว่า Ada มีอะไรดีกว่าเป็นพิเศษหรือไม่