อะไรคือข้อโต้แย้งต่อต้านการแยกทางคธูลู?


24

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

ฉันรู้โดยประสบการณ์ว่าการเขียน lexer / parser ด้วยมือ - ยกเว้นว่าไวยากรณ์เป็นเรื่องเล็กน้อย - เป็นกระบวนการที่ใช้เวลานานและเกิดข้อผิดพลาดได้ง่าย ดังนั้นฉันจึงเหลือสองตัวเลือก: ตัวแยกวิเคราะห์เครื่องปั่นà la yacc หรือห้องสมุด combinator เช่น Parsec อดีตก็ดีเช่นกัน แต่ฉันเลือกอย่างหลังด้วยเหตุผลต่าง ๆ และนำโซลูชันมาใช้ในภาษาที่ใช้งานได้

ผลลัพธ์ที่ได้นั้นค่อนข้างน่าประทับใจต่อสายตาของฉันรหัสนั้นสั้นกระชับหรูหราและอ่านง่าย / คล่องแคล่ว ฉันยอมรับว่ามันอาจดูแปลก ๆ ถ้าคุณไม่เคยตั้งโปรแกรมในสิ่งอื่นนอกจาก java / c # แต่สิ่งนี้จะเป็นจริงกับสิ่งที่ไม่ได้เขียนใน java / c #

ถึงจุดหนึ่งฉันถูกเพื่อนร่วมงานจู่โจมอย่างแท้จริง หลังจากเหลียวดูหน้าจอของฉันอย่างรวดเร็วเขาก็ประกาศว่ารหัสนั้นไม่สามารถเข้าใจได้และฉันไม่ควรบูรณาการแยกวิเคราะห์ แต่ใช้ stack และ String.Split เหมือนทุกคนทำ เขาทำเสียงดังมากและฉันไม่สามารถโน้มน้าวเขาได้บางส่วนเพราะฉันถูกจับด้วยความประหลาดใจและไม่มีคำอธิบายที่ชัดเจนส่วนหนึ่งเป็นเพราะความคิดเห็นของเขาไม่เปลี่ยนรูป ฉันเสนอให้อธิบายภาษาเขา แต่ก็ไม่มีประโยชน์

ฉันคิดว่าการอภิปรายกำลังจะปรากฏตัวต่อหน้าผู้บริหารอีกครั้งดังนั้นฉันจึงเตรียมข้อโต้แย้งที่มั่นคง

นี่คือเหตุผลสองสามข้อแรกที่มาถึงใจของฉันเพื่อหลีกเลี่ยงการแก้ปัญหาตาม String.Split:

  • คุณต้องใช้ ifs จำนวนมากเพื่อจัดการกับกรณีพิเศษและสิ่งต่าง ๆ หมุนวนออกจากการควบคุมอย่างรวดเร็ว
  • ดัชนีอาเรย์ฮาร์ดโค้ดจำนวนมากทำให้การบำรุงรักษาเจ็บปวด
  • ยากมากที่จะจัดการกับสิ่งต่าง ๆ เช่นการเรียกใช้ฟังก์ชันเป็นอาร์กิวเมนต์เมธอด (เช่นเพิ่ม ((เพิ่ม a, b), c)
  • ยากมากที่จะให้ข้อความแสดงข้อผิดพลาดที่มีความหมายในกรณีที่มีข้อผิดพลาดทางไวยากรณ์ (น่าจะเกิดขึ้น)
  • ฉันทั้งหมดเพื่อความเรียบง่ายความชัดเจนและการหลีกเลี่ยงสิ่งที่ชาญฉลาดที่ไม่จำเป็น แต่ฉันเชื่อว่ามันเป็นความผิดพลาดที่จะทำให้ทุกส่วนของ codebase ช้าลงดังนั้นแม้แต่เบอร์เกอร์ฟลิปเปอร์ก็สามารถเข้าใจได้ มันเป็นเหตุผลเดียวกับที่ฉันได้ยินว่าไม่ได้ใช้อินเทอร์เฟซไม่แยกความกังวลคัดลอก - วางโค้ด ฯลฯ ความสามารถด้านเทคนิคขั้นต่ำและความเต็มใจที่จะเรียนรู้จำเป็นต้องทำงานในโครงการซอฟต์แวร์หลังจากทั้งหมด (ฉันจะไม่ใช้อาร์กิวเมนต์นี้เพราะอาจฟังดูไม่เหมาะสมและการเริ่มต้นสงครามไม่ได้ช่วยใคร)

อะไรคือข้อโต้แย้งที่คุณชื่นชอบในการแยกวิเคราะห์ภาษาคธูลู ? *

* แน่นอนถ้าคุณสามารถโน้มน้าวฉันได้เขาก็จะมีความสุขเช่นกัน


9
ฟังดูแล้วเหมือนเพื่อนร่วมงานของคุณกำลังอาสาทำโครงการ DSL ให้คุณ!
GrandmasterB

23
"ฉันไม่ควรบูรณาการการแยกวิเคราะห์ แต่เพียงใช้สแต็กและสตริงแยกออกเหมือนทุกคนทำ" - ด่าคนนั้นน่าจะดีใจที่ไม่รู้จะไม่ทำร้าย ...
Michael Borgwardt

4
แนะนำเพื่อนร่วมงานของคุณว่าจะไม่กลับไปที่การสนทนานี้จนกว่าเขาจะอ่านหนังสือมังกรทั้งเล่มและผ่านการทดสอบ ไม่อย่างนั้นเขาไม่มีสิทธิ์ที่จะพูดคุยเรื่องใด ๆ ที่เกี่ยวข้องกับการแยกวิเคราะห์
SK-logic

4
ขออภัยใครเป็นผู้คิดค้นการแยกวิเคราะห์ใหม่
ร. ว.

2
ฉันคิดว่าหัวของฉันจะระเบิดอย่างแท้จริงในครั้งต่อไปที่ฉันเห็นใครบางคนที่ใช้คำว่า "แท้จริง" เปรียบเปรย

คำตอบ:


33

ความแตกต่างที่สำคัญระหว่างทั้งสองวิธีคือสิ่งที่เขาคิดว่าเป็นวิธีที่ถูกต้องเพียงอย่างเดียวคือสิ่งจำเป็น

  • วิธีการของคุณประกาศกฎอย่างชัดเจนเช่นกฎของไวยากรณ์คือ (เกือบ) เข้ารหัสโดยตรงในรหัสของคุณและห้องสมุด parser จะแปลงอินพุตดิบเป็นเอาต์พุตแจงโดยอัตโนมัติในขณะที่การดูแลของรัฐและสิ่งอื่น ๆ ที่ยากที่จะจัดการ รหัสของคุณถูกเขียนภายใน Abstraction หนึ่งเลเยอร์ซึ่งเกิดขึ้นพร้อมกับโดเมนปัญหา: การแยกวิเคราะห์ มันมีเหตุผลที่จะสมมติว่าความถูกต้องของพาร์เซกซึ่งหมายความว่ามีเพียงห้องเดียวสำหรับข้อผิดพลาดที่นี่คือว่าการกำหนดไวยากรณ์ของคุณผิด แต่จากนั้นอีกครั้งคุณมีวัตถุกฎที่มีคุณสมบัติครบถ้วนและพวกมันจะถูกทดสอบแยกได้ง่าย นอกจากนี้อาจเป็นเรื่องน่าสังเกตว่าไลบรารี parser ที่เป็นผู้ใหญ่มาพร้อมกับคุณสมบัติที่สำคัญอย่างหนึ่ง: การรายงานข้อผิดพลาด การกู้คืนข้อผิดพลาดที่มีค่าเมื่อการแยกวิเคราะห์ผิดพลาดนั้นไม่สำคัญ ตามหลักฐานแล้วฉันเรียกใช้ PHP parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM: D

  • วิธีการของเขาจัดการกับสตริงรักษาสถานะอย่างชัดเจนและยกระดับอินพุตดิบด้วยตนเองเพื่อแยกวิเคราะห์อินพุต คุณต้องเขียนทุกอย่างด้วยตัวเองรวมถึงการรายงานข้อผิดพลาด และเมื่อมีสิ่งผิดปกติเกิดขึ้นคุณก็หลงทางทั้งหมด

ประชดประกอบในความถูกต้องของ parser ที่เขียนด้วยวิธีการของคุณได้รับการพิสูจน์ค่อนข้างง่าย ในกรณีของเขามันเป็นไปไม่ได้เกือบ

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

CAR Hoare

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

ในท้ายที่สุดคำถามคือใครจะต้องรักษามันไว้? หากเป็นคุณก็เป็นสายของคุณไม่ว่าใครจะพูดว่าอะไร ถ้ามันจะเป็นเขาก็มีเพียงสองวิธี: หาวิธีที่จะทำให้เขาเข้าใจห้องสมุด parser หรือเขียน parser ที่จำเป็นสำหรับเขา ฉันขอแนะนำให้คุณสร้างมันขึ้นมาจากโครงสร้าง parser ของคุณ: D


คำอธิบายที่ยอดเยี่ยมของความแตกต่างระหว่างสองแนวทาง
smarmy53

6
ดูเหมือนว่าคุณเชื่อมโยงกับ TVTropes สำหรับโปรแกรมเมอร์ Goodbye บ่าย ...
Izkata

10

ไวยากรณ์ของนิพจน์การแยกวิเคราะห์ (เช่นวิธี Packrat parser) หรือตัวแยกวิเคราะห์ parser ไม่ใช่การสร้างการแยกวิเคราะห์ใหม่ เหล่านี้เป็นเทคนิคที่จัดตั้งขึ้นอย่างดีในโลกการเขียนโปรแกรมการทำงานและในมือข้างขวาก็สามารถอ่านได้มากกว่าทางเลือก ฉันได้เห็นการสาธิตที่น่าเชื่อถือของ PEG ใน C # เมื่อไม่กี่ปีที่ผ่านมาซึ่งจะทำให้เป็นเครื่องมือของฉันในการใช้ไวยากรณ์แรกที่ค่อนข้างง่าย

หากคุณมีวิธีการแก้ปัญหาที่หรูหราโดยใช้ตัวแยกวิเคราะห์ parser หรือ PEG มันควรจะขายค่อนข้างง่าย: มันขยายได้ค่อนข้างปกติอ่านได้ง่ายเมื่อคุณรู้สึกกลัวการเขียนโปรแกรมที่ใช้งานได้และบางครั้งอ่านง่ายกว่าตัวแยกวิเคราะห์ทั่วไป เสนอเครื่องมือแม้ว่ามันจะขึ้นอยู่กับไวยากรณ์และระดับประสบการณ์ที่คุณมีกับชุดเครื่องมือทั้งสอง มันค่อนข้างง่ายที่จะเขียนการทดสอบ แน่นอนว่ามีความคลุมเครือด้านไวยากรณ์บางอย่างที่อาจส่งผลให้ประสิทธิภาพการวิเคราะห์คำแย่ลงในกรณีที่เลวร้ายที่สุด (หรือการใช้หน่วยความจำจำนวนมากด้วย Packrat) แต่กรณีทั่วไปค่อนข้างดีและจริง ๆ แล้วความคลุมเครือของไวยากรณ์บางอย่าง ฉันจำได้

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

โดยส่วนตัวความชอบครั้งแรกของฉันเมื่อฉันต้องการสร้าง DSL คือใช้ Boo (.Net) หรือ Groovy (JVM) เนื่องจากฉันได้รับความแข็งแรงของภาษาการเขียนโปรแกรมที่มีอยู่ทั้งหมดและความสามารถในการปรับแต่งได้อย่างไม่น่าเชื่อ ไปยังไพพ์ไลน์คอมไพเลอร์โดยไม่ต้องใช้สิ่งที่น่าเบื่อที่ฉันต้องทำถ้าฉันเริ่มต้นจากศูนย์ (ลูปตัวแปรรูปแบบวัตถุ ฯลฯ ) ถ้าฉันอยู่ในร้านที่กำลังพัฒนา Ruby หรือ Lisp ฉันก็แค่ใช้สำนวนที่เข้าใจง่าย (metaprogramming ฯลฯ )

แต่ฉันสงสัยว่าปัญหาที่แท้จริงของคุณนั้นเกี่ยวกับวัฒนธรรมหรืออัตตา คุณแน่ใจหรือไม่ว่าผู้ร่วมงานของคุณจะไม่ประหลาดใจถ้าคุณใช้ Antlr หรือ Flex / Bison ฉันสงสัยว่า "การโต้เถียง" สำหรับวิธีการแก้ปัญหาของคุณอาจเป็นการต่อสู้ที่แพ้ คุณอาจต้องใช้เวลามากขึ้นในการทำวิธีที่นุ่มนวลกว่าซึ่งใช้เทคนิคการสร้างฉันทามติแทนที่จะดึงดูดต่อหน่วยงานจัดการในพื้นที่ของคุณ จับคู่การเขียนโปรแกรมและแสดงให้เห็นว่าคุณสามารถปรับเปลี่ยนไวยากรณ์ได้เร็วเพียงใดโดยไม่เสียสละการบำรุงรักษาและทำกระเป๋าสีน้ำตาลเพื่ออธิบายเทคนิคประวัติและอื่น ๆ อาจไปไกลกว่า 10 หัวข้อย่อยและ "หยาบคาย Q&A" ในบางกรณี การประชุมแบบเผชิญหน้า


9

ฉันไม่ชำนาญในการแยกขั้นตอนวิธีและไม่ชอบ แต่ฉันคิดว่าหลักฐานการพุดดิ้งอยู่ในการกิน ดังนั้นหากทุกอย่างล้มเหลวคุณสามารถเสนอให้เขาใช้เครื่องมือแยกวิเคราะห์ในแบบของเขา แล้วก็

  • เปรียบเทียบเวลาที่ลงทุนในโซลูชันทั้งสอง
  • เรียกใช้โซลูชันทั้งสองผ่านการทดสอบการยอมรับที่ครอบคลุมเพื่อดูว่ามีข้อบกพร่องน้อยกว่าและ
  • ให้ผู้พิพากษาอิสระเปรียบเทียบรหัสผลลัพธ์ในขนาดและความชัดเจนกับคุณ

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


นี่เป็นความคิดที่ยอดเยี่ยม! มันจะง่ายต่อการใช้เฟรมเวิร์กหน่วยทดสอบ commont ด้วย
smarmy53

1
+1 สำหรับการมีเพื่อนร่วมงานทำเวอร์ชันแยก ... OP เป็นหน้าที่หนึ่งในการสร้างมันขึ้นมาดังนั้นเขาจึงเป็นคนที่น่าจะสนับสนุนมันมากที่สุดไม่ใช่เพื่อนร่วมงาน เพียงแนะนำให้เขาทำงานอื่น ๆ ของเขาอาจจะเพียงพอที่จะทำให้เขาหลุดจากหลังคุณ
Izkata

7

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

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

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


คุณพูดถูกแล้วฉันรู้แล้วว่าวิธีการของฉันนั้นเหนือกว่า แต่ฉันไม่สามารถอธิบายออกมาได้ดีและน่าเชื่อถือ - นั่นคือข้อมูลทางเทคนิคที่ฉันกำลังมองหา เห็นด้วยด้าน "ปฏิสัมพันธ์ของมนุษย์" ของปัญหามีความสำคัญเท่ากับด้านเทคนิค (ถ้าไม่มาก)
smarmy53

4

ฉันจะย่อ:

การแยกทางคธูลูเป็นเรื่องยาก นั่นเป็นข้อโต้แย้งที่ง่ายและน่าเชื่อถือที่สุด

มันสามารถทำเคล็ดลับสำหรับภาษาที่เรียบง่าย; พูดภาษาปกติ มันอาจจะไม่ง่ายไปกว่าการแสดงออกปกติ

นอกจากนี้ยังสามารถทำเคล็ดลับสำหรับภาษาที่ซับซ้อนขึ้นอีกเล็กน้อย

อย่างไรก็ตามฉันต้องการเห็น Cthulhu parser สำหรับภาษาใด ๆ ที่มีการซ้อนหรือเพียงแค่ "stateful สำคัญ" - การแสดงออกทางคณิตศาสตร์หรือตัวอย่างของคุณ (การเรียกใช้ฟังก์ชันที่ซ้อนกัน)

ลองนึกภาพว่าจะเกิดอะไรขึ้นถ้ามีคนพยายามที่จะคธูลูตัวแยกวิเคราะห์สำหรับภาษาที่ไม่มีบริบท หากเขาฉลาดพอที่จะเขียนโปรแกรมแยกวิเคราะห์ที่ถูกต้องฉันพนันได้เลยว่าระหว่างการเขียนรหัสเขาจะ "ค้นพบ" โทเคนิซาตันแรกก่อนจากนั้นจึงแยกวิเคราะห์โคตรซ้ำ - ในบางรูปแบบ

หลังจากนั้นสิ่งที่เรียบง่าย: "เฮ้ดูสิคุณได้เขียนบางสิ่งที่เรียกว่าตัวแยกวิเคราะห์แบบวนซ้ำคุณรู้ไหมว่ามันสามารถสร้างขึ้นได้โดยอัตโนมัติจากคำอธิบายไวยากรณ์อย่างง่ายเช่นเดียวกับการแสดงออกปกติ?


เรื่องสั้นสั้น ๆ :
สิ่งเดียวที่สามารถหยุดยั้งคนไม่ให้ใช้วิธีการที่มีอารยธรรมคือความไม่รู้ของพวกเขา


1

บางทีการใช้ความหมายของ DSL ที่ดีก็มีความสำคัญเช่นกัน (ไวยากรณ์มีความหมาย แต่ก็หมายถึงความหมายด้วย) หากคุณไม่คุ้นเคยกับปัญหาเหล่านี้ฉันขอแนะนำให้อ่านหนังสือบางเล่มเช่นภาษาโปรแกรมเชิงปฏิบัติ (โดย M.Scott) และ Christian Queinnec เสียงกระเพื่อมในชิ้นเล็กๆ สำนักพิมพ์มหาวิทยาลัยเคมบริดจ์, 1996

การอ่านเอกสารล่าสุดในการประชุม DSL เช่นDSL2011ควรช่วยด้วย

การออกแบบและการใช้ภาษาเฉพาะโดเมนนั้นเป็นเรื่องยาก (และปัญหาส่วนใหญ่ไม่ได้แยกวิเคราะห์!)

ฉันไม่เข้าใจจริงๆว่าคุณหมายถึงอะไรโดยการแยกทางคธูลู ; ฉันคิดว่าคุณหมายถึงการแยกวิเคราะห์ในรูปแบบที่แปลกประหลาดอย่างใด


ลิงค์ที่ดี สำหรับคธูลูขอโทษฉันลืมลิงค์ไป มันมีการอ้างอิงถึงบทความ codinghorror คลาสสิก: codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html ฉันอัพเดทโพสต์ดั้งเดิม
smarmy53
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.