Система, с которой я работаю с банкоматом, - это С# и оракул, однако проблема, с которой я столкнулась, - это системная агностика (может случиться с системой с java и mysql или с любой другой интерфейсной и обратной связью):
У меня есть объект TransactionDetail
который может иметь 9 статусов
Open,
Complete,
Cancelled,
No Quote,
Quoted,
Instructed,
Declined,
Refunded,
Removed
Из моего опыта, когда нужно иметь дело с статусами в интерфейсном коде, он должен делать все возможное, чтобы избежать статуса объекта, имеющего сеттер. Это связано с тем, что статус является неотъемлемым качеством и должен определяться в тот момент, когда он необходим - другими словами, статус всегда должен определяться методом или получить только свойство и не устанавливать.
Таким образом, статусы извлекаются с помощью таких механизмов (это всего лишь фрагмент кода, но должен дать вам указание, как он работает)
public TransactionStatus TransactionStatus()
{
if (db.DeclinedTransactions.Any(o => o.TransactionId == this.TransactionId))
return TransactionStatus.Declined;
}
MI запрашивает эти статусы транзакций в представлении SQL, которые также будут содержать все данные, относящиеся к транзакции.
Если статус объекта можно определить только из данных самого объекта, то создаваемые столбцы могут решить эту проблему в базе данных. Но как насчет таких объектов, как TransactionDetail
которые охватывают несколько таблиц - нет расчетного механизма столбцов, который позволит "заглянуть" в другие таблицы.
Единственное решение, о котором я могу думать, это добавить функцию SQL, которая определяет состояние, а затем создать представление SQL, содержащее данные функции + из таблицы. То, что мне не нравится в этом подходе, заключается в том, что для этого требуется дублировать логику в коде и в базе данных.
Как следует проектировать систему вокруг состояния объекта, которое требуется определить, требует информации из более чем одной таблицы, таким образом, чтобы не требовалось дублировать механизмы в коде и в исходном тексте?
Если бы это был проект, над которым я работал, я бы не хотел создавать View для расчета этих данных.
Я бы посмотрел на мою бизнес-логику приложений.
Хотя полностью нормализованная база данных имеет смысл для администраторов баз данных, бывают случаи, когда производительность приложений и масштабируемость могут значительно выиграть от небольшой де-нормализации.
Если у вас есть надежная структура бизнес-логики (т.е. Четко определенные бизнес-объекты, хорошая инкапсуляция, надежные модульные тесты), то я лично хотел бы добавить это к бизнес-объектам.
Затем вы можете определить поведение статуса в коде и обновить явное состояние. Например, если внесение изменений в бизнес-объект, который помещает его в другой TransactionStatus
вы можете явно внести изменения в этот статус в бизнес-объект и сохранить все изменения в своей базе данных.
Обычный ответ на такое предложение дизайна заключается в том, что тогда вам необходимо обеспечить, чтобы вы несли синхронизацию двух вещей (явный статус и состояние объекта) - ответ на этот вопрос заключается в том, что есть только один кусок логики для осуществления этих изменений и что ваша бизнес-логика является водонепроницаемой, как описано выше.
Пример:
Обычным способом, который это делается, является использование SUM()
для вычисления суммы счета "на лету" в базе данных для заполнения значения Invoice.Total.
Но если моя бизнес-логика четко определена - возможно, я добавляю InvoiceItem к объекту Invoice в коде, а логика Add
также принимает значение из InvoiceItem и добавляет его в значение Invoice.Total
- тогда, когда я Invoice.Total
изменения, я также могу совершить это Invoice.Total значение.
Когда я хочу отобразить общее количество, у меня есть одно значение, вместо того, чтобы агрегировать в базе данных.