Ориентация на объекты важна именно потому, что возникают эти типы сценариев, и она дает вам инструменты для разумного проектирования абстракций, которые позволяют инкапсулировать сложность.
Реальный вопрос здесь в том, где вы заключаете эту сложность?
Итак, позвольте мне сделать шаг назад и поговорить о том, на какую «сложность» я здесь ссылаюсь. Ваша проблема (насколько я понимаю; исправьте меня, если я ошибаюсь) - это модель постоянства, которая не является эффективно используемой моделью для задач, которые необходимо выполнить с данными. Это может быть эффективным и полезным для других задач, но не для ваших задач.
Итак, что мы делаем, когда у нас есть данные, которые не представляют хорошую модель для наших средств?
Перевести. Это единственное, что вы можете сделать. Этот перевод - «сложность», о которой я говорю выше. Итак, теперь, когда мы признаем, что собираемся перевести модель, нам нужно определиться с парой факторов.
Нужно ли переводить оба направления? Оба направления будут переведены так же, как в:
(Tbl A, Tbl B) -> Obj X (читать)
Obj X -> (Tbl A, Tbl B) (напишите)
или операции вставки / обновления / удаления представляют другой тип объекта, так что вы читаете данные как Obj X, но данные вставляются / обновляются из Obj Y? Какой из этих двух способов вы хотите использовать, или если обновление / вставка / удаление невозможно, являются важными факторами, на которых вы хотите разместить перевод.
Куда вы переводите?
Вернемся к первому утверждению, которое я сделал в этом ответе; ОО позволяет вам инкапсулировать сложность, и здесь я имею в виду тот факт, что вы не только должны это делать, но вы должны инкапсулировать эту сложность, если хотите, чтобы она не просочилась и не просочилась во весь ваш код. В то же время важно осознавать, что у вас не может быть идеальной абстракции, поэтому беспокойтесь об этом меньше, чем о очень эффективной и полезной.
Опять сейчас; Ваша проблема в том, куда вы кладете эту сложность? Ну, у вас есть выбор.
Вы можете сделать это в базе данных, используя хранимые процедуры. Это имеет недостаток, заключающийся в том, что они часто не очень хорошо играют с ORM, но это не всегда так. Хранимые процедуры дают некоторые преимущества, в том числе производительность. Однако хранимые процедуры могут потребовать большого количества обслуживания, но вы должны проанализировать свой конкретный сценарий и сказать, будет ли обслуживание больше или меньше других вариантов. Я лично очень хорошо разбираюсь в хранимых процедурах, и этот факт наличия таланта снижает накладные расходы; никогда не стоит недооценивать ценность принятия решений на основе того, что вы знаете. Иногда неоптимальное решение может быть более оптимальным, чем правильное решение, потому что вы или ваша команда знаете, как его создать и поддерживать лучше, чем оптимальное решение.
Другой вариант в базе данных - это просмотры. В зависимости от вашего сервера базы данных они могут быть в высшей степени оптимальными или субоптимальными или даже неэффективными, одним из недостатков может быть время запроса в зависимости от того, какие параметры индексации доступны в вашей базе данных. Представления становятся еще лучшим выбором, если вам никогда не нужно вносить какие-либо изменения в данные (вставить / обновить / удалить).
Проходя мимо базы данных, у вас есть старый режим использования шаблона хранилища. Это проверенный временем подход, который может быть очень эффективным. Недостатки, как правило, включают в себя котельную пластину, но хорошо продуманные репозитории могут избежать некоторого количества этого, и даже когда они приводят к неудачному количеству котельной пластины, репозиторий, как правило, представляет собой простой код, который легко понять и поддерживать, а также представляет хороший API / абстракция. Также репозитории могут быть хороши для их модульной тестируемости, которую вы теряете с опциями в базе данных.
Существуют такие инструменты, как auto-mapper , которые могут сделать использование ORM правдоподобным, когда они могут выполнять перевод между моделью базы данных из orm в пригодные для использования модели, но некоторые из этих инструментов могут быть сложными для поддержания / понимания поведения, более похожего на магию; хотя они создают минимум служебного кода, что приводит к меньшим накладным расходам на обслуживание, если их хорошо понимать.
Затем вы шагаете дальше и дальше от базы данных , что означает, что будет больше кода, который будет иметь дело с непереведенной моделью персистентности, которая будет действительно неприятна. В этих сценариях вы говорите о включении слоя перевода в ваш пользовательский интерфейс, что, по вашему мнению, может быть и сейчас. Как правило, это очень плохая идея, и со временем она разрушается.
Теперь давайте начнем говорить сумасшедшие .
Object
Не только конечным быть все-все абстракция , которая существует. В течение многих лет было разработано множество абстракций, в которых информатика изучалась, и даже до этого из математики. Если мы собираемся начать проявлять креативность, давайте начнем говорить об известных доступных абстракциях, которые были изучены.
Там модель актера.Это интересный подход, потому что он говорит, что все, что вы делаете, - это отправляете сообщения другому коду, который эффективно делегирует всю работу этому другому коду, что очень эффективно для инкапсуляции сложности от всего вашего кода. Это может сработать, поскольку вы отправляете актеру сообщение «Мне нужен объект X, отправленный в Y», и у вас есть приемник, ожидающий ответа в местоположении Y, который затем обрабатывает объект X. Вы можете даже отправить сообщение с указанием «Мне нужен Obj X и вычисление Y, Z сделано для него», и тогда вам даже не нужно ждать; перевод происходит на другой стороне этого сообщения, и вы можете просто двигаться дальше, если вам не нужно читать его результат. Это может быть незначительное злоупотребление актерской моделью для ваших целей, но все зависит;
Другая граница инкапсуляции - это границы процесса. Они могут быть использованы для разделения сложности очень эффективно. Вы можете создать код перевода в виде веб-службы, где для связи используется простой HTTP, с использованием SOAP, REST или если вы действительно хотите использовать собственный протокол (не рекомендуется). STOMP совсем не плохой новый протокол. Или используйте обычный демон-сервис с системным каналом публичной памяти для очень быстрой связи с любым другим протоколом, который вы выберете. Это на самом деле имеет довольно хорошие преимущества:
- У вас может быть запущено несколько процессов, которые выполняют перевод для поддержки более старых и более новых версий одновременно, что позволяет обновлять службу перевода для публикации объектной модели V2, а затем отдельно позднее обновлять код потребления для работы с новым объектом. модель.
- Вы можете делать интересные вещи, такие как закрепление процесса на ядре для повышения производительности, вы также получаете определенную степень безопасности при таком подходе, делая единственный процесс, работающий с привилегиями безопасности, касающийся этих данных.
- Вы получите очень сильную границу, когда будете говорить о границах процесса, которые останутся неизменными, гарантируя минимальную утечку вашей абстракции в течение длительного времени, потому что написание кода в пространстве перевода не будет вызываться вне пространства перевода, так как они не будет разделять объем процесса, обеспечивая фиксированный набор сценариев использования по контракту.
- Возможность для асинхронных / неблокирующих обновлений проще.
Недостатки, очевидно, заключаются в большем обслуживании, чем это обычно необходимо, накладные расходы на связь влияют на производительность и обслуживание.
Существует множество способов инкапсулировать сложность, которые могут позволить поместить эту сложность во все более странные и любопытные места в вашей системе. Используя формы функций более высокого порядка (часто фальсифицированные с использованием шаблонов стратегий или различных других нечетных форм шаблонов объектов), вы можете делать очень интересные вещи.
Правильно, давайте начнем говорить о монаде. Вы можете создать этот слой перевода очень независимым способом из небольших специфических функций, которые выполняют независимые переводы, необходимые, но скрыть все эти функции перевода от невидимых, чтобы они были едва доступны для внешнего кода. Преимущество этого заключается в уменьшении зависимости от них, что позволяет им легко меняться, не оказывая большого влияния на внешний код. Затем вы создаете класс, который принимает функции более высокого порядка (анонимные функции, лямбда-функции, объекты стратегии, но вам нужно их структурировать), которые работают с любыми объектами типа модели OO. Затем вы позволяете базовому коду, который принимает эти функции, выполнять буквальное выполнение, используя соответствующие методы перевода.
Это создает границу, в которой весь перевод существует не только на другой стороне границы от всего вашего кода; он используется только на той стороне, что позволяет остальной части вашего кода даже не знать о нем ничего, кроме того, где находится точка входа для этой границы.
Хорошо, да, это действительно говорит сумасшедший, но кто знает; Вы можете просто быть сумасшедшим (серьезно, не берите монады с рейтингом сумасшествия ниже 88%, существует реальный риск получения телесных повреждений).