Что такое «мягкое кодирование»?

87

В этой статье Алекса Пападимулиса вы можете увидеть этот фрагмент:

private void attachSupplementalDocuments()
{
  if (stateCode == "AZ" || stateCode == "TX") {

    //SR008-04X/I are always required in these states
    attachDocument("SR008-04X");
    attachDocument("SR008-04XI");
  }

  if (ledgerAmnt >= 500000) {
    //Ledger of 500K or more requires AUTHLDG-1A
    attachDocument("AUTHLDG-1A");
  }

  if (coInsuredCount >= 5  && orgStatusCode != "CORP") {
    //Non-CORP orgs with 5 or more co-ins require AUTHCNS-1A
    attachDocument("AUTHCNS-1A");
  }
}

Я действительно не понимаю эту статью.

Я цитирую:

Если бы каждая константа бизнес-правила была сохранена в каком-то файле конфигурации, жизнь была бы намного [более ( sic )] трудной для всех, кто обслуживает программное обеспечение: было бы много файлов кода, которые совместно использовали один, большой файл (или, наоборот, куча крошечных конфигурационных файлов); развертывание изменений в бизнес-правилах требует не нового кода, а изменения файлов конфигурации вручную; и отладка намного сложнее.

Это аргумент против наличия целого числа «500000» в файле конфигурации или «AUTHCNS-1A» и других строковых констант.

Как это может быть плохой практикой?

В этом фрагменте «500000» не является числом. Это не, например, то же самое, что:

int doubleMe(int a) { return a * 2;}

где 2 - число, которое не нужно абстрагировать. Его использование очевидно, и оно не представляет собой то, что может быть использовано позже.

Наоборот, «500000» - это не просто число. Это значительная ценность, представляющая идею точки останова в функциональности. Этот номер можно использовать более чем в одном месте, но это не тот номер, который вы используете; это идея предела / границы, ниже которой применяется одно правило, а выше которого другое.

Как обращение к нему из файла конфигурации, или даже из того #define, constчто предоставляет ваш язык, хуже, чем включение его значения? Если впоследствии программе или другому программисту также потребуется эта граница, чтобы программное обеспечение сделало другой выбор, вы облажались (потому что при его изменении ничто не гарантирует, что оно изменится в обоих файлах). Это явно хуже для отладки.

Кроме того, если завтра правительство потребует «Начиная с 5/3/2050, вам нужно добавить AUTHLDG-122B вместо AUTHLDG-1A», эта строковая константа не является простой строковой константой. Это тот, который представляет идею; это просто текущая стоимость этой идеи (то есть «вещь, которую вы добавляете, если регистр превышает 500 КБ»).

Позвольте мне уточнить. Я не говорю, что статья неверна; Я просто не понимаю этого; возможно это не слишком хорошо объяснено (по крайней мере для моего размышления).

Я понимаю, что замена любого возможного строкового литерала или числового значения на постоянную, определяемую или конфигурационную переменную не только не нужна, но и усложняет вещи, но этот конкретный пример, кажется, не подпадает под эту категорию. Откуда ты знаешь, что тебе это не понадобится позже? Или кто-то еще в этом отношении?

К. Гкинис
источник
21
Сыграйте в загадку: какое имя будет хорошим для этих номеров? Я думаю, вы обнаружите, что либо имя не добавляет никакого значения, либо оно описывает все, что код уже описывает, и часто при добавлении неоднозначности («LedgerLimitForAuthDlg1A»?). Я нашел статью блестящей именно потому, насколько это актуально. Я поддерживал системы, в которых использовались оба подхода, и я могу вам сказать, что бизнес-правила принадлежат к коду - это значительно облегчает их отслеживание, поддержку и понимание. Когда вы используете конфигурацию, вам лучше заставить ее считаться - это намного дороже.
Luaan
2
Конфигурация должна быть зарезервирована для вещей, которые должны быть настроены. Если бизнес-правила в целом не настраиваются, то, если вы все-таки внесете их в конфигурацию, вы ничего не купите.
biziclop
Для соответственно продвинутых языков конфигурация принимает форму реальных подпрограмм, а не строк.
Турбьёрн Равн Андерсен

Ответы:

100

Автор предостерегает от преждевременной абстракции.

Линия if (ledgerAmt > 500000)выглядит как бизнес-правило, которое вы ожидаете увидеть для больших сложных бизнес-систем, требования которых невероятно сложны, но точны и хорошо документированы.

Обычно такие требования являются исключительными / крайними случаями, а не полезной многократно используемой логикой. Эти требования, как правило, принадлежат и поддерживаются бизнес-аналитиками и отраслевыми экспертами, а не инженерами

(Обратите внимание, что «владение» требованиями бизнес-аналитиками / экспертами в этих случаях обычно происходит, когда разработчики, работающие в специализированных областях, не обладают достаточным опытом в предметной области; хотя я все же ожидаю полной коммуникации / сотрудничества между разработчиками и экспертами в предметной области для защиты от двусмысленные или плохо написанные требования.)

При обслуживании систем, требования которых заполнены крайними случаями и очень сложной логикой, обычно нет способа бесполезно абстрагировать эту логику или сделать ее более обслуживаемой; Попытки создания абстракций могут легко привести к обратным последствиям - не только приводить к потере времени, но и к уменьшению объема поддерживаемого кода.

Как обращение к нему из файла конфигурации или даже из #define, const или того, что предоставляет ваш язык, хуже, чем включение его значения? Если впоследствии программе или другому программисту также потребуется эта граница, чтобы программное обеспечение сделало другой выбор, вы облажались (потому что при его изменении ничто не гарантирует, что оно изменится в обоих файлах). Это явно хуже для отладки.

Этот вид кода имеет тенденцию быть защищенным фактом, что у самого кода, вероятно, есть непосредственное соответствие требованиям; то есть, когда разработчик знает, что в требованиях 500000фигура встречается дважды, этот разработчик также знает, что она фигурирует дважды в коде.

Рассмотрим другой (в равной степени вероятный) сценарий, когда 500000в документе с требованиями встречается несколько мест, но эксперты по предмету решают изменить только один из них; там у вас есть еще худший риск того, что кто-то, изменяющий constзначение, может не осознавать, что 500000используется для обозначения разных вещей - поэтому разработчик меняет его в одном-единственном месте, которое он находит в коде, и заканчивает тем, что что-то нарушает не понимал, что они изменились.

Этот сценарий часто встречается в специальном юридическом / финансовом программном обеспечении (например, в логике страховых котировок) - люди, которые пишут такие документы, не являются инженерами, и у них нет проблем с копированием + вставкой целых кусков спецификации, изменением нескольких слов / цифр, но оставляя большую часть этого же.

В этих сценариях лучший способ справиться с требованиями копирования-вставки - это написать код копирования-вставки и сделать код максимально похожим на требования (включая жесткое кодирование всех данных).

Реальность таких требований заключается в том, что они обычно не остаются копировать + вставлять долго, а значения иногда меняются на регулярной основе, но они часто не меняются в тандеме, поэтому стараются рационализировать или абстрагировать эти требования или упростить в любом случае они создают больше головной боли при обслуживании, чем просто дословный перевод требований в код.

Бен Коттрелл
источник
28
Домен-специфический язык (DSL) может быть хорошим способом сделать код более похожим на документ с требованиями.
Ян
13
Другое преимущество DSL заключается в том, что также затрудняет случайное смешивание логики приложения, представления или персистентности с бизнес-правилами.
Эрик Эйдт
16
Думать, что ваше приложение достаточно особенное, чтобы гарантировать собственный DSL, обычно является высокомерием.
brian_o
8
Those requirements are typically owned and maintained by business analysts and subject matter experts, rather than by engineersчто не всегда хорошая идея. Иногда процесс превращения этих требований в код выявляет крайние случаи, когда требования либо недостаточно четко определены, либо определены таким образом, что это противоречит интересам бизнеса. Если бизнес-аналитики и разработчики могут сотрудничать для достижения общей цели, то можно избежать множества проблем.
kasperd
4
@BenCottrell Я не предлагал изменить правила, чтобы было проще писать программное обеспечение. Но когда в правилах много условий, вполне возможно, что какое-то взаимодействие между ними было пропущено при определении правил в первую очередь. Но когда вы превращаете спецификацию в код, разработчик должен заметить, что между этими условиями возможно взаимодействие. В этот момент возможно, что разработчик обнаружит, что строгое толкование спецификации приводит к непреднамеренной цене, которая позволила бы пользователям играть в систему.
Касперд
44

У статьи есть хороший момент. Как может быть плохой практикой извлекать константы в файл конфигурации? Это может быть плохой практикой, если это усложняет код без необходимости. Наличие значения непосредственно в коде намного проще, чем чтение его из файла конфигурации, и за написанным кодом легко следовать.

Кроме того, завтра правительство сообщит: «С 5/3/2050 вам нужно добавить AUTHLDG-122B вместо AUTHLDG-1A».

Да, тогда вы меняете код. Смысл статьи в том, что изменить код не сложнее, чем изменить файл конфигурации.

Подход, описанный в статье, не масштабируется, если вы получаете более сложную логику, но дело в том, что вы должны сделать суждение, и иногда простое решение просто является лучшим.

Откуда ты знаешь, что тебе это не понадобится позже? Или кто-то еще в этом отношении?

В этом смысл принципа ЯГНИ. Не проектируйте для неизвестного будущего, которое может оказаться совершенно другим, дизайн для настоящего. Вы правы, что, если значение 500000 используется в нескольких местах в программе, оно, конечно, должно быть извлечено в константу. Но это не тот случай в рассматриваемом коде.

Мягкое кодирование - это действительно вопрос разделения проблем . Информация о программном коде, которую вы знаете, может изменяться независимо от логики основного приложения. Вы никогда не будете жестко кодировать строку подключения к базе данных, потому что вы знаете, что она может измениться независимо от логики приложения, и вам нужно будет дифференцировать ее для разных сред. В веб-приложении нам нравится отделять бизнес-логику от HTML-шаблонов и таблиц стилей, поскольку они могут изменяться независимо и даже изменяться разными людьми.

Но в случае с примером кода жестко закодированные строки и числа являются неотъемлемой частью логики приложения. Возможно, что один файл может изменить свое имя из-за какого-то изменения политики вне вашего контроля, но также возможно, что нам нужно добавить новую проверку if-ветки для другого условия. Извлечение имен файлов и номеров фактически нарушает сплоченность в этом случае.

JacquesB
источник
4
Часто изменить код намного сложнее, чем файл конфигурации. Для первого вам может понадобиться разработчик и цикл сборки / выпуска системы, в то время как последний требует только изменения числа в поле в дружественном пользовательском интерфейсе конфигурации.
OrangeDog
6
@OrangeDog Да, так оно и выглядит на первый взгляд. Но если вы делаете что - то вроде этого, конфигурационный интерфейс будет ничего , кроме дружественных, с сотнями совершенно бессмысленных текстовых коробок с запросом для того, кто знает что. И теперь вы должны построить пользовательский интерфейс и задокументировать его. Имейте в виду, это не означает, что конфигурация никогда не будет хорошим способом - есть случаи, когда это абсолютно правильный выбор. Но не в любом из примеров в статье. А когда в последний раз законодательство меняло только номер? В последний раз, когда правила НДС менялись здесь, нам все равно пришлось повторить все расчеты.
Luaan
2
@OrangeDog: Здесь вы предполагаете, что конфигурация программного обеспечения предоставляет вам необходимые хуки для проверки, которую вам нужно сделать. Обратите внимание, что в ОП каждый и каждый ifоснован на другой переменной! Если нужная переменная недоступна из конфигурации, вам все равно нужно изменить программное обеспечение.
Матье М.
2
@OrangeDog, значит, вы предлагаете внести существенные изменения в логику программного приложения, без цикла разработки / выпуска / выпуска и соответствующего тестирования?
NPSF3000
3
@OrangeDog: ОК, вы используете YAML для настройки логики в примере. Поскольку логика включает в себя условные правила, вы найдете способ представить эти условные выражения в YAML. Поздравляю, вы заново изобрели Python. Почему бы тогда не написать все приложение на Python?
JacquesB
26

Далее в статье говорится о движке Enterprise Rule Engine, который, вероятно, является лучшим примером того, против чего он спорит.

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

Например, код состояния для сопоставления документа в примере может быть перемещен в файл конфигурации. Но тогда вам нужно будет выразить сложные отношения.

<statecode id="AZ">
    <document id="SR008-04X"/>
    <document id="SR008-04XI"/>
</statecode>

Может быть, вы также добавили бы сумму бухгалтерской книги?

<statecode id="ALL">
    <document id="AUTHLDG-1A" rule="ledgerAmt >= 50000"/>
</statecode>

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

Следует отметить, что эта статья была написана в 2007 году, когда подобные вещи были обычным подходом.

В настоящее время мы, вероятно, решили бы проблему с помощью внедрения зависимостей (DI). Т.е. у вас был бы «жесткий код»

InvoiceRules_America2007 : InvoiceRules

который вы бы заменили на жестко закодированный или более настраиваемый

InvoiceRules_America2008 : InvoiceRules

когда закон или бизнес-требования изменились.

Ewan
источник
4
Возможно, вам следует определить «DI». И, возможно, объяснить немного больше.
Василий Бурк
9
Почему этот файл не будет в системе контроля версий?
JDługosz
2
Если это зависит от клиента, есть ли в кодированной версии множество ifоператоров для разных значений для каждого клиента? Это звучит как то, что должно быть в файле конфигурации. Нахождение в том или ином виде файла, при прочих равных условиях, не является причиной для того, чтобы не контролировать / отслеживать / резервировать файл. @ewan , кажется, говорит , что файл DSL - не может быть сохранен как часть проекта по какой - то причине, когда даже без кода активы , такие как изображения и звуковые файлы и документы , конечно , есть .
JDługosz
2
Вы действительно должны реорганизовать значение "50000" из вашего XML и поместить его в отдельный файл конфигурации, не так ли? ... и это должно быть 500000, кстати.
Wildcard
1
@jdlugosz концепция ERE заключается в том, что вы покупаете систему, а затем настраиваете ее для своих нужд. возможно, потому что внутренние разработчики конкурировали с этими «гибкими» системами, они пытались подражать им. изменение контроля над конфигурацией, даже в системах крупных компаний, таких как IBM, часто запаздывало. Пункт продажи был быстрой переменой
Ewan
17

Наоборот, «500000» - это не просто число. Это значительная ценность, представляющая идею точки останова в функциональности. Этот номер можно использовать более чем в одном месте, но это не число, которое вы используете, а идея предела / границы, ниже которой применяется одно правило, и выше которого другое.

И это выражается в наличии (и я могу утверждать, что даже комментарий является излишним):

 if (ledgerAmnt >= 500000) {
    //Ledger of 500K or more requires AUTHLDG-1A
    attachDocument("AUTHLDG-1A");
  }

Это просто повторение того, что делает код:

LEDGER_AMOUNT_REQUIRING_AUTHLDG1A=500000
if (ledgerAmnt >= LEDGER_AMOUNT_REQUIRING_AUTHLDG1A) {
    //Ledger of 500K or more requires AUTHLDG-1A
    attachDocument("AUTHLDG-1A");
}

Обратите внимание, что автор предполагает, что значение 500000 связано с этим правилом; это не значение, которое может или может быть повторно использовано в другом месте:

Единственное изменение бизнес-правила, которое могло когда-либо учитывать это предыдущее мягкое кодирование, - это изменение суммы регистра, для которой требовалась форма AUTHLDG-1A. Любое другое изменение бизнес-правила потребует еще больше работы - настройка, документация, код и т. Д.

На мой взгляд, основной смысл статьи заключается в том, что иногда число - это просто число: оно не имеет никакого дополнительного значения, кроме того, что передается в коде, и его вряд ли можно использовать в другом месте. Следовательно, неуклюжее обобщение того, что код делает (сейчас) в имени переменной только для того, чтобы избежать жестко закодированных значений, в лучшем случае является ненужным повторением.

Танос Тинтинидис
источник
2
Если бы вы ввели константу LEDGER_AMOUNT_REQUIRING_AUTHLDG1A, вы бы больше не писали комментарий в коде. Комментарии плохо поддерживаются программистами. Если сумма когда-либо изменилась, ifусловие и комментарий вышли бы из синхронизации. Напротив, константа LEDGER_AMOUNT_REQUIRING_AUTHLDG1Aникогда не синхронизируется сама с собой и объясняет свое назначение без лишних комментариев.
ZeroOne
2
@ZeroOne: За исключением того, что если бизнес-правило изменяется на «Книга 500К или более, требуется AUTHLDG-1A и AUTHLDG-2B», вполне вероятно, что человек, добавляющий attachDocument("AUTHLDG-2B");строку, не сможет обновить имя константы одновременно. В этом случае, я думаю, код достаточно ясен, без комментариев и переменных-объяснений. (Хотя это может иметь смысл иметь условность с указанием соответствующего раздела документа бизнес - требований через комментарии кода При такой конвенции, кода комментария , что делает. , Что было бы уместно.)
ruakh
@ruakh, хорошо, тогда я бы реорганизовал константу для вызова LEDGER_AMOUNT_REQUIRING_ADDITIONAL_DOCUMENTS(что я, вероятно, должен был сделать в первую очередь). У меня также есть привычка вставлять идентификаторы бизнес-требований в сообщения коммитов Git, а не в исходный код.
ZeroOne
1
@ZeroOne: Но для AUTHLDG-3C сумма регистра фактически максимальна . А для AUTHLDG-4D соответствующее количество регистров зависит от состояния. (Вы уже поняли смысл? Для этого типа кода вы хотите, чтобы ваш код отражал бизнес-правила, а не некоторую попытку абстрагирования бизнес-правил, потому что нет никаких оснований ожидать, что эволюция бизнес-правил будет соответствовать абстракции вы приняли.)
Руах
2
Лично я не возражаю против ввода магического числа в коде, я возражаю против структурирования кода, поэтому ему нужны эти комментарии. Если бы это был я, я сделал бы каждый документ экземпляром enum со своим собственным attachIfNecessary()методом и просто перебрал бы все из них.
Дэвид Моулз
8

Другие ответы правильные и вдумчивые. Но вот мой короткий и сладкий ответ.

  Rule/value          |      At Runtime, rule/value…
  appears in code:    |   …Is fixed          …Changes
----------------------|------------------------------------
                      |                 |
  Once                |   Hard-code     |   Externalize
                      |                 |   (soft-code)
                      |                 |
                      |------------------------------------
                      |                 |
  More than once      |   Soft-code     |   Externalize
                      |   (internal)    |   (soft-code)
                      |                 |
                      |------------------------------------

Если правила и специальные значения появляются в одном месте в коде и не изменяются во время выполнения, то используйте жесткий код, как показано в вопросе.

Если правила или специальные значения появляются в нескольких местах кода и не изменяются во время выполнения, то программный код. Мягкое программирование для правила может определять определенный класс / метод или использовать шаблон Builder . Для значений мягкое кодирование может означать определение одной константы или перечисления для значения, которое будет использоваться в вашем коде.

Если правила или специальные значения могут измениться во время выполнения, вы должны их экстернализовать. Обычно это делается путем обновления значений в базе данных. Или обновите значения в памяти вручную пользователем, вводящим данные. Это также делается путем сохранения значений в текстовом файле (XML, JSON, обычный текст и т. Д.), Который многократно сканируется для изменения даты и времени изменения файла.

Базилик Бурк
источник
1
Мне нравится ваш ответ, но я думаю, что вы также должны подумать, изменится ли он при реализации. Это в основном уместно, если речь идет о продукте, который будет использоваться во многих организациях, которые могут, например, иметь разные правила относительно того, должен ли супервизор утверждать возмещение по X и т. Д. И т. Д.
Bloke Down The Pub
Согласился как с этим ответом, так и с комментарием о реализации. Вещи, над которыми я работаю, реализуются многими организациями, и многие из них имеют немного разные необходимые значения. Мы склонны хранить эти «настройки» в базе данных, а не в файле конфигурации, но принцип заключается в том, что мы не хотим делать разные сборки нашего программного обеспечения для каждой компании, которая его реализует (затем повторять эти разные сборки при каждом обновлении) ,
RosieC
7

Это ловушка, в которую мы попадаем, когда используем игрушечную задачу, а затем ставим только соломенные решения, когда пытаемся проиллюстрировать реальную проблему.

В приведенном примере не имеет значения, являются ли приведенные значения жестко закодированными как встроенные значения или определены как константы.

Именно окружающий код сделает пример ужасом обслуживания и кодирования. Если нет нет окружающих код, то фрагмент отлично, по крайней мере , в условиях постоянного рефакторинга. В среде, где рефакторинг, как правило, не происходит, разработчики этого кода уже мертвы по причинам, которые вскоре станут очевидными.

Видите ли, если есть код, окружающий его, тогда явно происходят плохие вещи.

Первое, что плохо, это то, что значение 50000 используется для другого значения где-нибудь, скажем, суммы бухгалтерской книги, в которой изменяется налоговая ставка в некоторых штатах ... затем, когда происходит изменение, сопровождающий не может узнать, когда он находит те два экземпляра 50000 в коде, означают ли они те же самые 50 Кб, или совершенно не связанные 50 Кб. И стоит ли вам искать 49999 и 50001, если кто-то тоже использовал их в качестве констант? Это не вызов для добавления этих переменных в файл конфигурации отдельного сервиса: но жесткое их кодирование в строке явно также неверно. Вместо этого они должны быть константами, определенными и определенными в пределах класса или файла, в котором они используются. Если два экземпляра 50k используют одну и ту же константу, то они, вероятно, представляют одно и то же законодательное ограничение; если нет, то, вероятно, нет; и так или иначе, у них будет имя,

Имена файлов передаются в функцию - attachDocument (), которая принимает базовые имена файлов в виде строки без пути или расширения. Имена файлов, по сути, являются внешними ключами для некоторой файловой системы, базы данных или везде, где attachDocument () получает файлы. Но строки ничего не говорят об этом - сколько там файлов? Какие типы файлов они? Как узнать, нужно ли обновлять эту функцию при открытии нового рынка? К каким типам вещей они могут быть прикреплены? Сопровождающий полностью оставлен в неведении, и все, что у него есть, - это строка, которая может появляться в коде несколько раз и означать разные вещи при каждом его появлении. В одном месте «SR008-04X» - чит-код. В другом это команда заказать четыре ракеты-носителя SR008. Здесь это имя файла? Это связано? Кто-то просто изменил эту функцию, упомянув другой файл, «КЛИЕНТ». Тогда вам, плохому сопровождающему, сказали, что файл «КЛИЕНТ» необходимо переименовать в «ЗАКАЗЧИК». Но строка «КЛИЕНТ» появляется 937 раз в коде ... где вы вообще начали искать?

Проблема игрушка является то , что значения все необычное и может быть разумно гарантированно быть уникальным кодом. Не «1» или «10», а «50 000». Не "клиент" или "отчет", а "SR008-04X".

По сути , единственный способ решить проблему непроницаемых непрозрачных констант состоит в том, чтобы поместить их в файл конфигурации какого-либо несвязанного сервиса.

Вместе вы можете использовать эти две ошибки, чтобы доказать любой аргумент.

Деви Морган
источник
2
Не проблема с игрушкой, не соломенный. Это то , что вы будете видеть все время в этих видах бизнес - приложений. Нет «открытия на новом рынке», нет повторного использования одного и того же числа (в конце концов, это в любом случае придало бы ему другое значение), и в любом случае, статья ничего не говорит против DRY - если есть две зависимости от значения, это будет перемещен в метод или константу. Покажите примеры того, как эти константы (из настроек конфигурации, это не имеет значения) должны быть названы, и где они должны храниться таким образом, чтобы это было в будущем и более понятно, чем код.
Луаан
4
Пример не ломается, потому что это проблема с игрушкой. Окружающий код всегда будет ужасным, потому что бизнес-правила, которые должно выполнять программное обеспечение, ужасны . Попытки обойти эту фундаментальную проблему с помощью механизмов правил и DSL и тому подобного часто являются затягиванием программиста , потому что решение проблем CS является более приятным, чем решение сложностей налоговых форм. Попытки достичь «элегантности» часто бывают глупыми, потому что конечной задачей программного обеспечения является моделирование сложной катастрофы.
whatsisname
Бизнес-правила могут быть ужасными, но это само по себе не оправдание для написания такого посредственного процедурного кода. (Я склонен согласиться с Пападимулисом, что моделировать и поддерживать правила проще в коде, чем в конфигурации, я просто думаю, что это должен быть лучший код.) Проблема с СУХОЙ, которую я вижу, это не магические числа, а повторяющиеся if (...) { attachDocument(...); }.
Дэвид Моулз
2

В этом есть несколько вопросов.

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

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

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

Кроме того, поскольку константа является закрытой, ее нельзя использовать где-либо еще в коде.

Затем составьте список всех правил и примените этот список.

Еще одна проблема заключается в том, как обрабатывать константы. 500000 может показаться неприметным, но нужно быть очень осторожным, чтобы убедиться, что он конвертируется правильно. Если применяется какая-либо арифметика с плавающей запятой, она может быть преобразована в 500 000,00001, поэтому сравнение с 500 000,00000 может быть неудачным. Или, что еще хуже, 500000 всегда работает как задумано, но 565000 почему-то дает сбой при конвертации. Убедитесь, что преобразование явное и сделано вами, а не угадыванием компилятором. Часто это делается путем преобразования его в какой-то BigInteger или BigDecimal перед его использованием.

изогнутый
источник
2

Хотя это прямо не упоминается в этом вопросе, я хотел бы отметить, что важно не скрывать бизнес-логику в коде.

Код, как и в приведенном выше примере, который кодирует заданные извне бизнес-требования, должен действительно businesslogicнаходиться в отдельной части дерева исходных текстов, возможно, названной или что-то в этом роде, и следует позаботиться о том, чтобы он кодировал только бизнес-требования просто, легко и наглядно. кратко, насколько это возможно, с минимумом шаблонного и с четкими и информативными комментариями.

Его не следует смешивать с «инфраструктурным» кодом, который реализует функциональные возможности, необходимые для реализации бизнес-логики, такие как, например, реализация attachDocument()метода в примере или, например, пользовательский интерфейс, протоколирование или код базы данных в целом. В то время как один способов обеспечения такого разделения является «программный код» всей бизнес-логики в файле конфигурации, это далеко не единственный (или лучший) метод.

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

В идеале такой код также должен быть написан на предметно-ориентированном языке, чтобы обеспечить разделение между бизнес-логикой и базовой инфраструктурой, но это может быть излишне сложно для базового внутреннего приложения. Тем не менее, если вы, например, продаете программное обеспечение нескольким клиентам, каждый из которых нуждается в своем собственном настраиваемом наборе бизнес-правил, простой язык сценариев для конкретного домена (возможно, например, основанный на песочнице Lua ) может быть просто идеальным.

Илмари Каронен
источник
Это именно то, о чем я думал !!! Когда логика глубоко погружена в код, как эксперт в области / предметной области или бизнес-пользователь может увидеть используемые значения и логику, чтобы убедиться в их правильности, и диагностировать поведение системы? Файл конфигурации делает одну вещь видимой . Должны быть какие-то средства для улучшения видимости бизнес-правил, даже если это делает кодирование «более сложным». Я могу принять тонкий класс или набор классов, которые выполняют свою работу, не смешивая при этом другие проблемы - при условии, что у бизнес-пользователя есть средства для доступа и понимания их.
ErikE