SqlDataSource vs ObjectDataSource

Вот мое предложение в C ++

Я попытался наложить как минимальное ограничение на тип итератора, так как я мог так это решение предполагал просто итератор вперед, и он может быть const_iterator. Это должно работать с любым стандартным контейнером. В тех случаях, когда аргументы не имеют смысла, это вызывает std :: invalid_argumnent

#include <vector>
#include <stdexcept>

template <typename Fci> // Fci - forward const iterator
std::vector<std::vector<Fci> >
enumerate_combinations(Fci begin, Fci end, unsigned int combination_size)
{
    if(begin == end && combination_size > 0u)
        throw std::invalid_argument("empty set and positive combination size!");
    std::vector<std::vector<Fci> > result; // empty set of combinations
    if(combination_size == 0u) return result; // there is exactly one combination of
                                              // size 0 - emty set
    std::vector<Fci> current_combination;
    current_combination.reserve(combination_size + 1u); // I reserve one aditional slot
                                                        // in my vector to store
                                                        // the end sentinel there.
                                                        // The code is cleaner thanks to that
    for(unsigned int i = 0u; i < combination_size && begin != end; ++i, ++begin)
    {
        current_combination.push_back(begin); // Construction of the first combination
    }
    // Since I assume the itarators support only incrementing, I have to iterate over
    // the set to get its size, which is expensive. Here I had to itrate anyway to  
    // produce the first cobination, so I use the loop to also check the size.
    if(current_combination.size() < combination_size)
        throw std::invalid_argument("combination size > set size!");
    result.push_back(current_combination); // Store the first combination in the results set
    current_combination.push_back(end); // Here I add mentioned earlier sentinel to
                                        // simplyfy rest of the code. If I did it 
                                        // earlier, previous statement would get ugly.
    while(true)
    {
        unsigned int i = combination_size;
        Fci tmp;                            // Thanks to the sentinel I can find first
        do                                  // iterator to change, simply by scaning
        {                                   // from right to left and looking for the
            tmp = current_combination[--i]; // first "bubble". The fact, that it's 
            ++tmp;                          // a forward iterator makes it ugly but I
        }                                   // can't help it.
        while(i > 0u && tmp == current_combination[i + 1u]);

        // Here is probably my most obfuscated expression.
        // Loop above looks for a "bubble". If there is no "bubble", that means, that
        // current_combination is the last combination, Expression in the if statement
        // below evaluates to true and the function exits returning result.
        // If the "bubble" is found however, the ststement below has a sideeffect of 
        // incrementing the first iterator to the left of the "bubble".
        if(++current_combination[i] == current_combination[i + 1u])
            return result;
        // Rest of the code sets posiotons of the rest of the iterstors
        // (if there are any), that are to the right of the incremented one,
        // to form next combination

        while(++i < combination_size)
        {
            current_combination[i] = current_combination[i - 1u];
            ++current_combination[i];
        }
        // Below is the ugly side of using the sentinel. Well it had to haave some 
        // disadvantage. Try without it.
        result.push_back(std::vector<Fci>(current_combination.begin(),
                                          current_combination.end() - 1));
    }
}
16
задан abatishchev 22 September 2011 в 07:43
поделиться

2 ответа

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

Однако, когда приложение спроектировано и построено для долгосрочной работы и предполагает, что некоторые вещи (требования, пожелания клиентов, в конечном итоге схема базы данных) могут менять, тогда было бы гораздо разумнее ввести правильный "бизнес-уровень" - смоделировать свои бизнес-объекты как объекты, а затем предоставить отображение из базовой базы данных в эти бизнес-объекты.

Как говорится, вы можете решить почти что угодно в информатике с помощью еще одного уровня косвенности (или абстракции) - здесь то же самое.

УБЕДИТЕЛЬ: вы можете перейти прямо к базе данных, и, конечно, сначала и для первой итерации это возможно (или, возможно, ) самый быстрый способ. Но в долгосрочной перспективе, когда приложение построено на долгое время, это обычно быстрый и грязный способ - стоимость содержания, стоимость обслуживания, затраты и усилия, необходимые для изменения в соответствии с вашими требованиями. и потребности ваших клиентов будут расти, и довольно быстро это быстрое и грязное решение уже не выглядит так хорошо, с точки зрения усилий.

Итак, резюмируя свою точку зрения: да, изначально использование прямого источника данных SQL могло бы быть быстрее и проще - так что используйте его, когда это важный момент: чтобы сделать что-то для быстрой демонстрации, приложение в стиле доказательства концепции. Но в долгосрочной перспективе, когда вы смотрите на продолжительность жизни приложения, обычно стоит потратить немного больше усилий (дизайн и кодирование), чтобы добавить этот уровень абстракции, чтобы ваши веб-страницы не зависели напрямую от деталей база данных внизу.

Marc

23
ответ дан 30 November 2019 в 21:11
поделиться

Если у вас есть бизнес-уровень, который вы используете в своих проектах, ObjectDataSource - естественный выбор. Это хорошо сочетается со многими ORM, и многие из них предоставляют дополнительные преимущества (проверка, отмена и т. Д.). Он также позволяет вам получить доступ к любым другим свойствам и методам, которые есть у ваших бизнес-объектов, а не только к прямым полям SQL. Это может очень пригодиться при связывании, поскольку позволяет вам просто выполнять привязку к свойствам в разметке, вместо того, чтобы писать много кода.

Если вы идете по этому пути, смешивание SQLDataSource и ObjectDataSource может привести к путанице у следующего разработчика, который заберет ваш проект. В этом случае я придерживаюсь ObjectDataSource для согласованности кода.

Если у вас нет бизнес-уровня и вы просто используете SQL напрямую, используйте SQLDataSource.

3
ответ дан 30 November 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: