Собсна, вот какая штука. Достался мне один очень большой и очень лохматый проект лохматых годов. Который пока требуется "причесать", потом уже думать рефакторинг и прочие. Проект рабочий и используется.
Сам проект — толстый GUI клиент к СУБД. По всему коду тьма развесистых строк вида
std::string strQuery = "SELECT ... (бла-бла-бла)... %ll, ... %d"; // встречаются очень длинные строки запросы на два десятка строк кода в редакторе
Трогать всё это рекомендуется осторожно.
Какую та часть потихоньку переношу в процедуры и функции в БД.
Есть какой та best practice как и где всё это хранить, SQL строки, что ли?! Может в ресурсах? Но тогда искать их там и править еще сложней будет, т.к. не будет ясен контекст.
Кто как делает?! Какие рекомендации?
P.S. Т.к. мопед не мой, и особого опыта написания и проектирования больших проектов работающих с СУБД не имею.
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Здравствуйте, Мёртвый Даун, Вы писали:
МД>P.S. Т.к. мопед не мой, и особого опыта написания и проектирования больших проектов работающих с СУБД не имею.
Хранить как строковые константы. Можно в том же файле где используется, а можно завести отдельный.
Здравствуйте, Мёртвый Даун, Вы писали:
МД>Всем привет!
МД>Какую та часть потихоньку переношу в процедуры и функции в БД.
Вот этого я бы делать не стал. Минусы: тестировать сложней, сложность вследствие размазанности кода возрастает, зависимость от субд возрастает, версионность кода поддерживать сложней.
Здравствуйте, dya-victor, Вы писали:
DV>Здравствуйте, Мёртвый Даун, Вы писали:
МД>>Всем привет!
МД>>Какую та часть потихоньку переношу в процедуры и функции в БД.
DV>Вот этого я бы делать не стал. Минусы: тестировать сложней, сложность вследствие размазанности кода возрастает, зависимость от субд возрастает, версионность кода поддерживать сложней.
Согласен в какой та степени. Но мой намёк и посыл был: как бы вообще избавиться от SQL строк в текстах программы?
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Здравствуйте, BlackEric, Вы писали:
BE>Здравствуйте, Мёртвый Даун, Вы писали:
МД>>P.S. Т.к. мопед не мой, и особого опыта написания и проектирования больших проектов работающих с СУБД не имею.
BE>Хранить как строковые константы. Можно в том же файле где используется, а можно завести отдельный.
Т.е. все SQL строки-запросы всё таки хранить в тексте программы? Чтото типа:
Ну, пока что действительно, мне видится это правильным решением.
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Здравствуйте, Мёртвый Даун, Вы писали:
DV>>Вот этого я бы делать не стал. Минусы: тестировать сложней, сложность вследствие размазанности кода возрастает, зависимость от субд возрастает, версионность кода поддерживать сложней.
МД>Согласен в какой та степени. Но мой намёк и посыл был: как бы вообще избавиться от SQL строк в текстах программы?
BlackEric до меня ответил, поэтому я не стал ) Можно еще рассмотреть внешний файл, если есть необходимость менять запросы на лету.
Здравствуйте, Мёртвый Даун, Вы писали:
МД>Всем привет!
МД>Собсна, вот какая штука. Достался мне один очень большой и очень лохматый проект лохматых годов. Который пока требуется "причесать", потом уже думать рефакторинг и прочие. Проект рабочий и используется. МД>Сам проект — толстый GUI клиент к СУБД. По всему коду тьма развесистых строк вида
МД>
МД>std::string strQuery = "SELECT ... (бла-бла-бла)... %ll, ... %d"; // встречаются очень длинные строки запросы на два десятка строк кода в редакторе
МД>
МД>Трогать всё это рекомендуется осторожно. МД>Какую та часть потихоньку переношу в процедуры и функции в БД. МД>Есть какой та best practice как и где всё это хранить, SQL строки, что ли?! Может в ресурсах? Но тогда искать их там и править еще сложней будет, т.к. не будет ясен контекст.
МД>Кто как делает?! Какие рекомендации?
МД>P.S. Т.к. мопед не мой, и особого опыта написания и проектирования больших проектов работающих с СУБД не имею.
Я бы посмотрел в сторону написания ORM'а и полного отказа от хранения sql строк в коде.
МД>std::string strQuery = "SELECT ... (бла-бла-бла)... %ll, ... %d"; // встречаются очень длинные строки запросы на два десятка строк кода в редакторе
МД>
Елси это реальная строчка из проекта, то для меня подозрительны тут 2 вещи:
1) Использование типа std::string вместо строковых литералов char const* const. Зачем загонять строку запроса в контейнер, содержимое которого можно поменять во время исполнения программы? Ни разу не сталкивался с такой необходимостью.
2) С какой целью используются флаги форматирования %ll, %d и не грозит ли это SQL injection? Может быть, для таких запросов нужно использовать prepared statements.
МД>Трогать всё это рекомендуется осторожно.
Это самое главное условие. Хорошо, если доступ к БД сгруппирован в отдельном слое классов или функций. Тогда неважно как хранятся запросы в программе, они ведь не будут видимы остальному коду.
Здравствуйте, PM, Вы писали:
PM>1) Использование типа std::string вместо строковых литералов char const* const. Зачем загонять строку запроса в контейнер, содержимое которого можно поменять во время исполнения программы? Ни разу не сталкивался с такой необходимостью.
Очевидно, запрос формируется в run time. Это нормальная практика.
PM>2) С какой целью используются флаги форматирования %ll, %d и не грозит ли это SQL injection? Может быть, для таких запросов нужно использовать prepared statements.
Там могут поставляться имена полей и таблиц для запроса. prepared statements тут не помогут.
Здравствуйте, Мёртвый Даун, Вы писали:
МД> Сам проект — толстый GUI клиент к СУБД. МД> // встречаются очень длинные строки запросы на два десятка строк кода в редакторе
МД>Кто как делает?! Какие рекомендации?
рекомендую все переносить в базу данных (процедуры, вьюхи). задача клиента будет подставить правильные аргументы при вызове. при необходимости можно использовать динамические запросы на стороне базы (см. https://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html )
можно будет менять запросы в базе без перекомпиляции клиента
если же текст запросов не получается выкинуть из C++ кода, то желательно изолировать возню с ними : перетащить форматирование запросов в отдельный файл. при желании код форматирования можно будет покрыть тестами
пример (мета-код):
//query.cpp
std::string ComposeQueryToGetCustomers(int ageFilter)
{
//fight with sprintf, long queries and SQL injectionsreturn sprintf("SELECT * FROM Customers WHERE Age > %d", ageFilter);
}
//FatGUI.cpp
OnClick()
{
int ageFilter = intBox.Value;
std::string q = ComposeQueryToGetCustomers(ageFilter);
std::vector<Customer> c = FetchRecords<Customer>(query, ConvertRecordSetToCustomer);
}
Здравствуйте, Igore, Вы писали:
I>Здравствуйте, Мёртвый Даун, Вы писали:
МД>>Какие рекомендации? I>1) Спрятать всё за DAO.
Ну понятно что можно каких угодно прослоек наделать... I>2) Попробовать odb
А вот за это спасибо! буду посмотреть!
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Здравствуйте, Мёртвый Даун, Вы писали:
МД>>>Какие рекомендации? I>>1) Спрятать всё за DAO. МД>Ну понятно что можно каких угодно прослоек наделать... I>>2) Попробовать odb МД>А вот за это спасибо! буду посмотреть!
Насколько я помню, ODB использует свой препроцессор чтобы обойти отсутствие compile-time reflection в языке, что может быть довольно радикально для давно существующего проекта.
Я использовал более классический подход — безопасные C++ обертки типа SOCI, cppDB, edba
Здравствуйте, Мёртвый Даун, Вы писали:
МД>Т.е. все SQL строки-запросы всё таки хранить в тексте программы? Чтото типа:
.............................. МД>Ну, пока что действительно, мне видится это правильным решением.
Не уверен, что это решение верное.
В наших проектах я сделал подгрузку файлов *.sql из каталога SQL — там хранятся все эти строки "SELECT...FROM...".
Каталог SQL — там же, где и исполнимый (*.exe файл) модуль приложения.
Явная выгода- если надо что-то менять, не нужно трогать: ни код приложения, ни саму БД.
Здравствуйте, AlexGin, Вы писали:
AG>Не уверен, что это решение верное. AG>В наших проектах я сделал подгрузку файлов *.sql из каталога SQL — там хранятся все эти строки "SELECT...FROM...". AG>Каталог SQL — там же, где и исполнимый (*.exe файл) модуль приложения. AG>Явная выгода- если надо что-то менять, не нужно трогать: ни код приложения, ни саму БД.
Мне просто любопытно, был ли хоть один случай когда после изменения SQL запроса действительно не пришлось менять ни схему БД, ни код приложения?
Здравствуйте, PM, Вы писали:
PM>Мне просто любопытно, был ли хоть один случай когда после изменения SQL запроса действительно не пришлось менять ни схему БД, ни код приложения?
В прошлом проекте время от времени хинты разные добавляли, например. И потом, один и тот же набор данных можно получить разными запросами.