Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Архитектурное решение


Автор: cupper 10.9.2012, 12:33
Представьте что у вас есть базовый абстрактный класс Database. Есть подклассы Mysql, Oracle, .... Есть фабрика котор умнеет создавать конечные экземпляры, т.е. Mysql, Oracle.
Есть такое понятие как uri_list, для случая распределенной БД. 

Вопрос, кто должен отвечать за перебор этих самых uri_list в случае реконекта ?
Первый способ:
Код

some_function()
{
    size_t uri_count = 0;
    Database db(DBFactory::create(++uri_count % GetUriList().size()));
    while(true)
    {
        try{
            log("Connecting");
            db->connect();
            log("Connected");
            
            // infinity loop
            while(do_something());
        }
        catch(SqlException){
            log("Disconnected");
            db.disconnect()
            db.reset(DBFactory::create(++uri_count % GetUriList().size()))
            sleep(reconnect_timeout);
            continue;
        }
        catch(){exit(1)};
    }
    
}

Тут все тривиально, сразу видна логика работа с БД. Конечный экземпляр Database, будь то Mysql или Oracle, знать не знает о том, что у нас может быть несколько БД, незнает о том что нужно делать паузы между реконнектами и тому подобное. Database это примитив который умеет только самое необходимое.
Проблема в том что, таких функций some_function в коде может быть несколько, в разных модулях например. И в один прекрасный момент, нужно будет что то поменять в логике работы с БД. В моем случае это было добавление паузы при реконнекте 
Код

sleep(reconnect_timeout);

И как следовало ожидать, в одном месте таки забыли добавить, и вылезло это аж только через пару месяцев. Ужас короче.

Второй способ: собственно над ним я сейчас как раз и думаю. Как сделать так что бы не переусложнять примитив Database но при этом спрятать всю логику в одном месте.
Например за перключением alias'ов (uri_list) может отвечать фабрика DBFactory. Пихать это в конечную реализацию Mysql не кошерно потому что придется дублировать в других классах типа Oracle.

А еще нужно спрятать логирование, паузу при реконнекте, да и сам процесс реконнекта завуалировать под одну операцию а не 
Код

log("Disconnected");
db.disconnect()
db.reset(DBFactory::create(++uri_count % GetUriList().size()))
sleep(reconnect_timeout);
....
log("Connecting");
db.connect()
log("Connected");


PS. почему в топике про С++... не нашел более подходящего, а язык реализации как раз С++

Автор: bsa 10.9.2012, 12:41
Посмотри, как это сделано у "конкурентов": http://soci.sourceforge.net/

Автор: xvr 11.9.2012, 11:28
Сделайте proxy между Database и его клиентами. И пусть этот proxy и обрабатывает реконекты (внутри запроса от клиента)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)