Які аргументи проти розбору способу Ктулху?


24

Мені було доручено реалізувати мову домену для інструменту, який може стати досить важливим для компанії. Мова проста, але не тривіальна, вона вже дозволяє вкладати цикли, об'єднання рядків тощо, і практично впевнені, що інші конструкції будуть додані в міру просування проекту.

З досвіду я знаю, що написання лексема / аналізатора вручну - без граматики є тривіальним - це трудомісткий і схильний до помилок процес. Тож мені залишилися два варіанти: генератор парсера à la yacc або бібліотека комбінаторів на зразок Parsec. Перший також був хорошим, але я вибрав другий з різних причин і реалізував рішення на функціональній мові.

Результат для мене досить вражаючий, код дуже лаконічний, елегантний і читабельний / вільний. Зізнаюсь, це може виглядати трохи дивно, якщо ви ніколи не програмували нічого, крім java / c #, але тоді це було б правдою для нічого, що не написано в java / c #.

У якийсь момент, однак, мене буквально напав колега. Після швидкого погляду на мій екран він заявив, що код незрозумілий і що я не повинен винаходити розбір, а просто використовувати стек і String.Split, як всі. Він зробив багато шуму, і я не зміг його переконати, частково тому, що мене сприйняли зненацька і не мали чіткого пояснення, частково тому, що його думка була непорушною (жоден каламбур не призначений). Я навіть запропонував пояснити йому мову, але безрезультатно.

Я впевнений, що обговорення збирається повторно перед керівництвом, тому я готую кілька вагомих аргументів.

Ось кілька перших причин, які мені спадають на думку уникати рішення на основі String.Split:

  • тобі потрібно чимало ifs для обробки спеціальних справ, і речі швидко виходять з-під контролю
  • багато індексів жорсткого коду масиву робить технічне обслуговування болісним
  • надзвичайно важко обробляти такі речі, як виклик функції як аргумент методу (наприклад, add ((add a, b), c)
  • дуже важко надати значущі повідомлення про помилки у разі помилок синтаксису (дуже ймовірно, що трапиться)
  • Я все для простоти, ясності та уникаю зайвих розумних криптовалют, але я також вважаю, що це помилка притупляти кожну частину кодової бази, так що навіть фліппер із гамбургер може це зрозуміти. Це той самий аргумент, який я чую за те, що не використовую інтерфейси, не приймаю розділення проблем, копіюючи-вставляючи код і т. Д. Для роботи над програмним проектом потрібен мінімум технічної компетентності та готовності вчитися. (Я не буду використовувати цей аргумент, оскільки це, мабуть, буде образливим, і розпочати війну ніхто не допоможе)

Які ваші улюблені аргументи проти розбору способу Cthulhu ? *

* звичайно, якщо ти зможеш переконати мене, він правий, я також буду абсолютно щасливий


9
Мені здається, що ваш колега добровільно робить проект DSL для вас!
GrandmasterB

23
"Я не повинен винаходити синтаксичний розбір, а просто використовувати стек і String.Split, як всі" - чорт, цей хлопець повинен бути радий, що незнання не зашкодить ...
Майкл Боргвардт

4
Порадьте своєму колезі не повертатися до цієї дискусії, якщо він не прочитає всю Книгу Драконів і не здасть тест. Інакше він не має права обговорювати щось, що стосується розбору.
SK-логіка

4
вибачте, хто винаходив розбір?
rwong

2
Я думаю, що моя голова буквально вибухне наступного разу, коли я побачу когось, що в переносному значенні вживає слово "буквально".

Відповіді:


33

Критична різниця між двома підходами полягає в тому, що той, який він вважає єдино правильним способом, є імперативним, а ваш - декларативним.

  • Ваш підхід явно декларує правила, тобто правила граматики (майже) безпосередньо кодуються у вашому коді, і бібліотека аналізатора автоматично перетворює необроблений вхід у проаналізований вихід, опікуючись станом та іншими речами, які важко обробляти. Ваш код записується в одному шарі абстракції, який збігається з проблемною областю: розбором. Доцільно припустити правильність парсека, а це означає, що єдине місце для помилок - це те, що ваше граматичне визначення неправильне. Але знову ж таки у вас є повністю кваліфіковані об'єкти правила, і вони легко перевіряються ізольовано. Крім того, варто відзначити, що зрілі бібліотеки парсера постачаються з однією важливою особливістю: повідомлення про помилки. Пристойне відновлення помилок при розборі пішло не так, це не банально. Як доказ я посилаюсь на PHP parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM: D

  • Його підхід маніпулює рядками, явно підтримує стан і піднімає сировину вручну на проаналізований вхід. Ви повинні все написати самостійно, включаючи повідомлення про помилки. А коли щось піде не так, ти повністю втрачаєшся.

Іронія полягає в тому, що правильність аналізатора, написаного вашим підходом, доволі легко доводиться. У його випадку це майже неможливо.

Існує два способи побудови дизайну програмного забезпечення: Один із способів - зробити його настільки простим, що явно немає недоліків, а інший спосіб - зробити його таким складним, що явних недоліків немає. Перший метод набагато складніше.

CAR CAR Hoare

Ваш підхід є більш простим один. Все, що перешкоджає йому, це трохи розширити свій обрій. Результат його підходу завжди буде викривленим, незалежно від того, наскільки широкий ваш горизонт.
Якщо чесно, мені здається, що хлопець - просто невігласний дурень, який страждає на синдром Блуба , достатньо нахабний, щоб вважати, що ви неправий і кричить на вас, якщо він вас не розуміє.

Врешті-решт, питання: хто повинен буде це підтримувати? Якщо це ти, то це твій дзвінок, незалежно від того, що хтось каже. Якщо це буде йому, то є лише дві можливості: знайти спосіб зробити так, щоб він зрозумів бібліотеку парсера або написати імперативний парсер для нього. Я пропоную вам створити його з вашої структури аналізатора: D


Відмінне пояснення різниці між двома підходами.
smarmy53

6
Ви, мабуть, зв’язалися з TVTropes для програмістів. Прощай вдень ...
Ізката

10

Граматика виразів синтаксичного розбору (наприклад, підхід до аналізатора Packrat) або комбінатор парсера не винаходить синтаксичний аналіз. Це добре усталені методики у світі функціонального програмування, і, в правильних руках, вони можуть бути читабельнішими за альтернативи. Я бачив досить переконливу демонстрацію PEG в C # кілька років тому, що насправді зробило б це моїм інструментом першої вдачі для порівняно простих граматик.

Якщо у вас є елегантне рішення, використовуючи комбінатори парсера або PEG, його продати слід досить просто: це досить розширюється, як правило, порівняно легко читати, коли ви переживаєте свій страх перед функціональним програмуванням, а іноді легше читати, ніж типовий генератор парсера Пропозиція інструментів, хоча це дуже залежить від граматики та рівня досвіду роботи з будь-яким набором інструментів. Також досить просто написати тести для. Звичайно, є кілька граматичних неоднозначностей, які можуть призвести до дуже жахливого аналізу продуктивності в гірших сценаріях (або великого споживання пам'яті в Packrat), але середній випадок є досить пристойним, і насправді деякі граматичні двозначності краще обробляються з PEG, ніж LALR, як Я пригадую.

Використання спліт та стека працює з більш простими граматиками, ніж PEG, або може підтримувати, але велика ймовірність, що з часом ви або погано будете винаходити рекурсивний спуск, або у вас з’явиться нечіткий набір поведінки, який ви будете виконувати на групі допомога в поданні ціною надзвичайно неструктурованого коду. Якщо у вас є лише прості правила токенізації, це, мабуть, не так вже й погано, але якщо ви додаєте складності, це, мабуть, буде найменш ремонтованим рішенням. Я б потягнувся до генератора аналізатора.

Особисто моїм першим нахилом, коли мені потрібно створити DSL, було б використовувати щось на кшталт Boo (.Net) або Groovy (JVM), оскільки я отримую всю силу існуючої мови програмування та неймовірну налаштованість, будуючи макроси та прості налаштування до конвеєра компілятора, без того, щоб реалізовувати нудні речі, які я б у кінцевому підсумку робив, якби я починав з нуля (циклі, змінні, модель об'єкта тощо). Якби я був у магазині, що займався розробкою Ruby або Lisp, я просто використовував ідіоми, які мають сенс там (метапрограмування тощо)

Але я підозрюю, що ваше справжнє питання стосується культури або егоїстів. Ви впевнені, що ваш колега не в рівній мірі б злякався, якби ви використовували Antlr або Flex / Bison? Я підозрюю, що "сперечатися" за ваше рішення може бути програшною битвою; можливо, вам доведеться витратити більше часу на тендітніший підхід, який використовує методи побудови консенсусу, а не звертатися до місцевих органів управління. Парне програмування та демонстрація того, як швидко ви можете змінити коригування граматики, не приносячи шкоди технічному обслуговуванню, і зробивши коричневий мішок, щоб пояснити техніку, її історію і так далі, може піти далі, ніж на 10 кульових очок і "грубих запитань" у деяких конфронтаційна нарада.


9

Я не добре розбираюся в алгоритмах розбору тощо, але думаю, що доказ пудингу є в їжі. Тож якщо все інше не вдасться, ви можете запропонувати йому здійснити аналізатор його шляху. Потім

  • порівняйте час, вкладений у будь-які рішення,
  • запустіть обидва рішення за допомогою всебічного тесту на прийняття, щоб побачити, у яких менше помилок, і
  • мати незалежного суддю порівняння отриманого коду за розміром і чіткістю з вашим.

Щоб тестування було справді справедливим, можливо, ви хочете, щоб обидва рішення реалізували один і той же API, а також використовувати загальну тестову панель (або одиничну рамку тестування, відому вам обом). Ви обидва могли написати будь-яку кількість та різновид функціональних тестових випадків та переконатися, що його власне рішення проходить усі вони. І звичайно, в ідеалі жоден з вас не повинен мати доступ до реалізації іншого до встановленого терміну. Вирішальним тестом було б перехресне тестування обох рішень за допомогою тестового набору, розробленого іншим розробником.


це чудова ідея! Використовувати рамки тестування комунальних одиниць також було б просто.
smarmy53

1
+1 за те, щоб колега працював у роздвоєній версії ... ОП був завданням його створити, тож саме той, хто, швидше за все, повинен буде його підтримувати, а не колега. Тільки запропонувавши це йому, крім своєї іншої роботи, може бути достатньо, щоб зірвати його зі спини.
Ізката

7

Ви задали це питання так, ніби у вас є технічне запитання, але, як ви, напевно, вже знали, тут немає жодного технічного питання. Ваш підхід надзвичайно перевершує те, що зламати щось на рівні персонажів.

Справжня проблема полягає в тому, що ваш (імовірно, більш досвідчений) колега невпевнено і відчуває загрозу вашим знанням. Ви не будете переконувати його технічними аргументами ; це просто зробить його більш захисним. Натомість вам доведеться знайти якийсь спосіб полегшити його страхи. Я не можу запропонувати багато пропозицій, але ви можете спробувати проявити високу повагу до його знань про застарілий код.

Нарешті, якщо ваш менеджер погоджується з його сумлінними технічними аргументами та відкидає ваше рішення, тоді я думаю, вам доведеться шукати іншу посаду. Зрозуміло, що ви були б більш цінними і більш цінними в більш досконалій організації.


Ти маєш рацію, я вже знав, що мій підхід є вищим, проте мені не вдалося вийти з хорошим переконливим поясненням - це технічна інформація, яку я шукаю. Погоджена сторона проблеми "взаємодія між людьми" настільки ж важлива, як і технічна (якщо не більше).
smarmy53

4

Я коротко:

Розбирати шлях Ктулху важко. Це найпростіший і переконливий аргумент проти цього.

Це може зробити трюк для простих мов; скажімо, звичайні мови. Це, мабуть, не буде простішим, ніж звичайний вираз, хоча.

Це також може зробити трюк для трохи складніших мов.

Однак я хотів би побачити аналізатор Cthulhu для будь-якої мови з вкладенням, або просто "значно значущий" - математичні вирази або ваш приклад (вкладені виклики функції).

Уявіть, що буде, якби хтось спробував проаналізувати аналізатор такої (нетривіальної без контексту) мови. За умови, що він достатньо розумний, щоб написати правильний аналізатор, я б покладався на те, що під час кодування він "виявить" спершу токенізатор, а потім рекурсивний синтаксичний аналіз - у якійсь формі.

Після цього річ проста: "Гляди, ти написав щось, що називається рекурсивним аналізатором спуску! Чи знаєш ти, що це може генеруватися автоматично з простого опису граматики, як і звичайні вирази?


Короткий короткий огляд:
Єдине, що може перешкодити комусь використовувати цивілізований підхід, - це їх незнання.


1

Можливо, робота над хорошою семантикою DSL також важлива (синтаксис має значення, але також і семантика). Якщо ви не знайомі з цими питаннями, я б запропонував прочитати деякі книги, наприклад, Прагматика мов програмування (від М.Шотта) та Крістіан Квінке. Лис невеликими шматочками . Cambridge University Press, 1996.

Читання останніх робіт на конференціях DSL, наприклад DSL2011, також повинно допомогти.

Розробка та реалізація мови, що відповідає домену, є складною (і більшість труднощів не є розбором!).

Я насправді не розумію, що ти маєш на увазі, аналізуючи шлях Ктулху ; Я думаю, ти просто маєш намір розібратися якось химерно.


Хороші посилання. Щодо Ктулху, вибачте, я забув посилання. Це посилання на класичну статтю про кодування помилок : codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html . Я оновив оригінальну публікацію.
smarmy53
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.