Рядки жорсткого кодування, які ніколи не зміняться


39

Отже, в моїх спробах написати програму для сполучення дієслів (алгоритмічно, а не через набір даних) для французької мови, я зіткнувся з невеликою проблемою.

Алгоритм сполучення дієслів насправді досить простий для 17-ти або більше випадків дієслів і працює за певною схемою для кожного випадку; Таким чином, суфікси сполучення для цих 17 класів є статичними і, швидше за все, незабаром не зміняться. Наприклад:

// Verbs #1 : (model: "chanter")
    terminations = {
        ind_imp: ["ais", "ais", "ait", "ions", "iez", "aient"],
        ind_pre: ["e", "es", "e", "ons", "ez", "ent"],
        ind_fut: ["erai", "eras", "era", "erons", "erez", "eront"],
        participle: ["é", "ant"]
    };

Це флективні суфікси для найпоширенішого класу дієслова французькою мовою.

Існують і інші класи дієслів (нерегламенти), сполучення яких також, ймовірно, залишаться статичними протягом наступного чи двох століть. Оскільки вони нерегулярні, їх повні сполучення повинні бути включені статично, оскільки вони не можуть надійно з'єднатись із шаблону (також є лише [за моїм рахунком] 32 нерегламенти). Наприклад:

// "être":
    forms = {
        ind_imp: ["étais", "étais", "était", "étions", "étiez", "étaient"],
        ind_pre: ["suis", "es", "est", "sommes", "êtes", "sont"],
        ind_fut: ["serai", "seras", "sera", "serons", "serez", "seront"],
        participle: ["été", "étant"]
    };

Я міг би помістити все це в XML або навіть JSON і десеріалізувати його, коли це потрібно використовувати, але чи є сенс? Ці рядки є частиною природної мови, яка змінюється, але повільною швидкістю.

Мене хвилює те, що роблячи "правильний" спосіб і десеріалізуючи деяке джерело даних, я не тільки ускладнив проблему, яка не повинна бути складною, але я також повністю відслідковувала цілі цілі алгоритмічний підхід: не використовувати джерело даних! У C # я міг просто створити клас під namespace Verb.Conjugation(наприклад class Irregular), щоб розмістити ці рядки в переліченому типі або щось подібне, замість того, щоб забивати їх у XML і створювати class IrregularVerbDeserializer.

Тому питання: чи доречно жорстко рядків коду, які дуже малоймовірно , щоб зміни в протягом життя програми? Звичайно, я не можу гарантувати на 100%, що вони не зміняться, але ризик проти вартості майже тривіальний, щоб зважити в моїх очах - жорстке кодування є кращою ідеєю тут.

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


26
Чи можете ви в майбутньому використовувати це програмне забезпечення іншою мовою, відмінною від французької?

10
Алгоритмічний підхід чи ні, зрозуміло, що вам просто доведеться жорстко кодувати ці 32 * 20 рядки (і більше, коли ви додаєте більше мов), і єдине реальне питання - де їх розмістити. Я б вибирав, де вам зручніше, що здається, що це було б у коді на даний момент. Ви завжди можете перемістити їх пізніше.
Іксрек

1
@ChrisCirefice Це звучить для мене досить оптимально. Дій.
Іксрек

2
@Gusdor Я не думаю, що ти читаєш чітко - я сказав, що схеми сполучення , швидше за все, ніколи не змінюватимуться або не змінюватимуться так рідко, що перекомпіляція кожні 100 років чи так буде добре. Звичайно, код зміниться, але як тільки рядки будуть там, як я їх хочу, якщо я не буду рефакторинг, вони будуть статичними протягом наступних 100 років.
Chris Cirefice

1
+1. Не кажучи вже про те, що через 60-100 років вартість або не буде, або взагалі буде замінена кращою версією.
HarryCBurn

Відповіді:


56

чи доречно рядки жорсткого коду, які навряд чи зміняться протягом життя програми? Звичайно, я не можу гарантувати на 100%, що вони не зміниться, але ризик проти вартості майже тривіальний, щоб зважити в моїх очах - жорстке кодування - це краща ідея тут

Мені здається, ти відповів на власне запитання.

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

Я б пішов з найпростішим підходом до реалізації, поки не знайду вагомої причини зробити його складнішим.


Дякую Ден, ось це я зрозумів. Написання XML-схеми для цього, наявність іншого файлу для відстеження та необхідність написання інтерфейсу для дезаріалізації даних просто здавалося надмірним, враховуючи, що там просто не так багато рядків, і оскільки це природна мова, навряд чи це кардинально зміниться. в наступні 100 років. На щастя, нині в мовах програмування ми маємо фантастичні способи абстрагувати ці необроблені дані за приємним інтерфейсом, наприклад, French.Verb.Irregular.Etreякий би містив дані мого запитання. Я думаю, що це все гаразд;)
Кріс Сірефіс

3
+1 Тут, з табору Ruby, я б розпочав жорстке кодування матеріалів і перемістив його на конфігурацію за необхідності. Не передчасно переробляйте проект, роблячи речі, які можна налаштувати. Це просто сповільнює вас.
Overbryd

2
Зауважте: деякі групи мають інше визначення "жорстке кодування", тому майте на увазі, що цей термін означає кілька речей. Існує добре розпізнаний антидіапазон, коли ви твердо кодуєте значення у операторах функції, а не створюєте структури даних, як у вас є ( if (num == 0xFFD8)). Цей приклад повинен стати чимось подібним if (num == JPEG_MAGIC_NUMBER)майже у всіх випадках з міркувань читабельності. Я просто зазначаю, тому що слово "жорстке кодування" часто піднімає волоски на шиях людей (як у мене) через таке почергове значення цього слова.
Корт Аммон

@CortAmmon JPEG має багато чарівних чисел. Звичайно JPEG_START_OF_IMAGE_MARKER?
користувач253751

@immibis Ваш вибір постійного називання, ймовірно, кращий, ніж мій.
Корт Аммон

25

Ви міркуєте не так.

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

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

  • Чи будете ви з певністю, близькою до 100%, найближчим часом поширити додаток на інші мови? Якщо так, то вам слід було зараз експортувати речі у файли JSON або XML (для слів, частин слів тощо) та динамічні мови (для правил), а не змушувати себе перезаписувати основну частину програми.

  • Або є лише незначна ймовірність того, що додаток буде розширено десь у майбутньому, і в цьому випадку YAGNI наказує, що найпростіший підхід (той, який ви зараз використовуєте) - кращий?

В якості ілюстрації візьміть перевірку орфографії Microsoft Word. Скільки речей, на вашу думку, є кодованими?

Якщо ви розробляєте текстовий процесор, ви могли б почати з простим орфографічних двигуном з HARDCODED правил і навіть HARDCODED словом: if word == "musik": suggestSpelling("music");. Швидко ви почнете рухати слова, а потім правити себе поза кодом. Інакше:

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

Як ви підкреслили себе:

Дуже мало правил з французької могло бути застосовано до японців.

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

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


1
Ну, звичайно, там не все важко закодовано: P, так що я думаю, це дійсно зводиться до визначення того, як я хочу, щоб інтерфейс виглядав так, щоб я міг застосувати його до декількох мов. Проблема полягає в тому, що я ще не знаю всіх мов досить добре, тому це фактично неможливо. Я думаю, що одне, що, можливо, вам не вистачає, - це те, що моделі кон'югації (це все, про що я говорю) є дуже статичними в мові, і це справді є чимось конкретним випадком. У французькій мові існує близько 17 зразків сполучення для дієслів. Це не скоро продовжиться ...
Кріс Крірефіс

4
Я не погоджуюсь - я не думаю, що має сенс переміщувати що-небудь за межами коду, перш ніж це, природно, відбувається через рефакторинг. Почніть з однієї мови, додайте інші - в якийсь момент реалізація ILanguageRule поділиться достатньою кількістю коду, що просто ефективніше мати єдину параметризовану реалізацію з XML (або іншим файлом). Але навіть тоді ви можете виявитись японцями, які мають зовсім іншу структуру. Починаючи з натискання інтерфейсу на XML (або подібного), випрошується лише зміни інтерфейсу, а не реалізації.
ptyx

2
Примітка: якщо ви хочете додати більше мов, це не означає переміщення мов у конфігураційний файл! Ви однаково могли б мати LanguageProcessorклас з кількома підкласами. (Фактично, "конфігураційний файл" - це насправді клас)
user253751

2
@MainMa: Чому ви вважаєте проблемою перекомпіляцію під час додавання слова? Вам доведеться перекомпілювати будь-яку іншу зміну коду, і перелік слів, мабуть, є тією частиною коду, яка, найменше, може змінитися з часом.
ЖакБ

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

15

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

Наприклад:

  • Вилучення текстів інтерфейсу у файли ресурсів. Це дозволяє непрограмісту редагувати та перевіряти читання текстів, а також дозволяє додавати нові мови, додаючи нові локалізовані файли ресурсів.

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

  • Перевірка орфографії, у якій є словник слів, проти яких можна перевірити. Ви можете додавати нові слова та мови, не змінюючи логіку програми.

Але також є складність накладних витрат з вилученням конфігурації, і це не завжди має сенс.

Рядки можуть бути жорстко кодованими, коли фактична рядок не може змінитися без зміни логіки програми.

Приклади:

  • Компілятор для мови програмування. Ключові слова не дістаються до конфігурації, оскільки кожне ключове слово має певну семантику, яка повинна підтримуватися кодом у компіляторі. Додавання нового ключового слова завжди потребуватиме змін коду, тому значення вилучення рядків у файл конфігурації не має значення.
  • Реалізація протоколу: Напр. HTTP-клієнт матиме твердо кодовані рядки, такі як "GET", "type-type" тощо. Тут рядки є частиною специфікації протоколу, тому вони є частинами коду, що найменш міняються.

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

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


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


1
Власне, у коментарі до MainMa я зазначив, що писати DSL для цього було б безглуздо, тому що дуже мало природних мов досить схожі, щоб зробити це вартим зусиль. Можливо, французька / іспанська / італійська буде досить близькою , але насправді не варто докладати додаткових зусиль, враховуючи, що кількість правил є дуже статичною для будь-якої мови. Інші моменти, які ви згадуєте про складність, були моїми точними турботами, і я думаю, ви чудово зрозуміли, про що я питав у своєму питанні, і ви дали чудову відповідь з прикладами, тому +1!
Кріс Сірефіс

5

Я погоджуюсь на 100% з відповіддю Дена Пішельмана, але хотів би додати одне. Питання, яке ви повинні задати собі тут, "хто збирається підтримувати / розширювати / виправляти список слів?". Якщо правила дотримання певної мови (певний розробник, я думаю, ви завжди) дотримується завжди, то використовувати зовнішній файл конфігурації немає сенсу, якщо це ускладнює справи - ви не отримаєте жодної вигоди від це. З цієї точки зору, буде доцільно жорсткий код таких списків слів, навіть якщо вам доведеться час від часу їх змінювати, якщо це достатньо для доставки нового списку в рамках нової версії.

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


Це хороший момент - однак, дуже ймовірно, що я стану єдиною людиною, яка фактично підтримує код, принаймні протягом наступних кількох років. Хороша частина цього полягає в тому, що, хоча рядки будуть жорстко закодовані, це дуже невеликий набір рядків / правил, які навряд чи можуть змінитися незабаром (так як це природна мова, яка не розвивається занадто багато років-до -рік). З цього приводу, правила сполучення, рядки закінчення дієслів тощо, ймовірно, будуть однаковими для нашого життя :)
Chris Cirefice

1
@ChrisCirefice ": саме мій погляд.
Doc Brown

2

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

Це дозволить заощадити багато проблем із підтримкою списку. У своєму VCS ви можете легко визначити, чи змінив алгоритм команда чи просто виправити помилку сполучення. Також список може знадобитися в майбутньому додати у випадках, які ви не розглянули. Тим більше, що кількість перерахованих 32 неправильних дієслів не здається точною. Хоча вони, схоже, охоплюють часто використовувані, я знайшов посилання на 133 чи навіть 350 з них.


Бергі, я планував відокремлювати дані від алгоритму. Те, що ви зауважуєте про французьких нерегулярних членів - визначення неправильного неправильно розуміється. Що я маю на увазі, коли говорю неправильно , це дієслова, які не можна «обчислити», або поєднати лише з інфінітивної форми. Неправильні дієслова взагалі не мають конкретного шаблону, і тому вони повинні мати чітко вказані сполучники (наприклад, французька мова Verb.Conjugation.Irregular`). З технічної
точки зору

0

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

Незалежно від того, як виражаються правила, чи потрібно вам додати мову змінити правило: скільки коду та файлів потрібно редагувати?

В ідеалі додавання нової мови повинно бути можливим, додавши файл "english.xml" або новий "EnglishRules реалізує ILanguageRules". Текстовий файл (JSON / XML) дає вам перевагу, якщо ви хочете змінити його за межами життєвого циклу збірки, але вам потрібна складна граматика, синтаксичний аналіз та їх буде важче налагодити. Файл коду (Java) дозволяє висловлювати складні правила більш простим способом, але вимагає відновлення.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.