Библиотека классов с поддержкой нескольких стратегий сохранения.
-
02-07-2019 - |
Вопрос
Я разрабатываю библиотеку классов C++, содержащую классы модели предметной области, и я хотел бы добавить поддержку создания экземпляров этих классов из различных механизмов сохранения, т.е.базы данных и файл.Пользователю библиотеки классов должен быть предоставлен интерфейс(?), с помощью которого можно запрограммировать класс, который может передавать данные из/в механизм персистентности.
Я знаю шаблон объекта доступа к данным, который, кажется, работает для Java, но я не совсем уверен, как применить его к C++.Есть ли другие решения?
Решение
C++ поддерживает множественное наследование, поэтому вы можете иметь универсальный API персистентности и наследовать механизм персистентности.При этом все равно придется использовать самоанализ для получения метаданных класса, но эта проблема все равно возникнет на любом уровне персистентности.
В качестве альтернативы вы можете сделать что-то подобное, но использовать метаданные для управления генератором кода, который заполняет «Getters» и «Setters» для уровня персистентности.
Любой уровень персистентности обычно использует тот или иной подход, поэтому ваша проблема заключается в подключении механизма загрузки к уровню персистентности.Я думаю, что это немного отличает вашу проблему от одного уровня персистентности, но решает ее с другой стороны.Вместо того, чтобы создавать классы предметной области на платформе персистентности, вы предоставляете набор классов предметной области с крючками для инфраструктуры персистентности, к которой третьи лица могут подключить свой механизм доступа к данным.
Я думаю, что как только вы предоставите доступ к метаданным класса и обратным вызовам, механизм сохранения станет относительно простым.Посмотрите на компоненты метаданных любой удобной среды сопоставления O/R C++ и поймите, как они работают.Инкапсулируйте это с помощью API в одном из базовых классов классов вашей предметной области и предоставьте общий API-интерфейс получения/установки для создания экземпляров или сохранения.Остальное зависит от человека, реализующего уровень персистентности.
Редактировать: Я не могу придумать библиотеку C++ с таким типом подключаемого механизма сохранения, который вы описываете, но я сделал кое-что на Python, куда можно было бы добавить этот тип средства.Конкретная реализация использовала средства Python, не имеющие прямого эквивалента на C++, хотя основной принцип, вероятно, можно было бы адаптировать для работы с C++.
В Python вы можете перехватить доступ к переменным экземпляра, переопределив __getattr()__
и __setattr()__
.Механизм персистентности фактически незаметно поддерживает собственный кэш данных.Когда функциональность была добавлена в класс (с помощью множественного наследования), она переопределила поведение системы по умолчанию для доступа к членам и проверила, соответствует ли запрашиваемый атрибут чему-либо в его словаре.В этом случае вызов был перенаправлен на получение или установку элемента в кэше данных.
Кэш имел собственные метаданные.Он знал об отношениях между сущностями в своей модели данных и знал, какие имена атрибутов следует перехватывать для доступа к данным.То, как это работало, отделяло его от уровня доступа к базе данных и могло (по крайней мере теоретически) позволить использовать механизм сохранения с разными драйверами.Не существует внутренней причины, по которой вы не могли бы (например) создать драйвер, который сериализовал бы его в XML-файл.
Сделать что-то подобное на C++ было бы немного сложнее, и, возможно, не удастся сделать доступ к кэшу объектов таким же прозрачным, как в этой системе.Вероятно, лучше всего использовать явный протокол, который загружает и сбрасывает состояние объекта в кеш.Код для этого вполне можно сгенерировать из метаданных кэша, но это нужно будет делать во время компиляции.Возможно, вы сможете что-то сделать с помощью шаблонов или переопределив ->
оператору, чтобы сделать протокол доступа более прозрачным, но это, наверное, больше хлопот, чем пользы.
Другие советы
Ускорить сериализацию предоставляет некоторые весьма полезные вещи для работы с сериализацией типов C++, но насколько хорошо они будут соответствовать желаемому интерфейсу, я не знаю.Он поддерживает как навязчивый, так и ненавязчивый дизайн, поэтому является довольно гибким.
Я бы избегал сериализации, ИМХО, мы реализовали это для одного из наших приложений в MFC еще в 1995 году, мы были достаточно умны, чтобы использовать независимое управление версиями объектов и файлов, но со временем вы получаете много старого беспорядочного кода.
Представьте себе определенные сценарии: устаревшие классы, устаревшие члены и т. д., каждый из которых представляет новую проблему.Теперь мы используем сжатые потоки типа XML, можем добавлять новые данные и поддерживать обратную совместимость.
Чтение и запись файла абстрагируются от сопоставления данных с объектами, теперь мы можем переключать форматы файлов, добавлять импортеры/экспортеры без изменения наших основных бизнес-объектов.
При этом некоторые разработчики любят сериализацию, но я лично обнаружил, что переключение кодовой базы, платформ, языков, наборов инструментов — все это вызывает множество проблем, чтение и запись ваших данных не должны быть одной из них.
Кроме того, использование стандартного формата данных с некоторым собственным ключом означает, что намного проще работать со сторонними организациями.
Возможно, вам захочется посмотреть повысить сериализацию.Не пользовавшись им, не могу сказать, рекомендовать его или нет.Библиотеки Boost обычно высокого качества.