Группировка связанных переменных и операций? - PullRequest
0 голосов
/ 29 июля 2011

В Code Complete, глава 10, рекомендуется сгруппировать связанные операторы, и приведен следующий пример:

void SummarizeData(...) {
    ...
    GetOldData( oldData, &numOldData );
    GetNewData( newData, &numNewData );
    totalOldData = Sum( oldData, numOldData );
    totalNewData = Sum( newData, numNewData );
    PrintOldDataSummary( oldData, totalOldData, numOldData );
    PrintNewDataSummary( newData, totalNewData, numNewData );
    SaveOldDataSummary( totalOldData, numOldData );
    SaveNewDataSummary( totalNewData, numNewData );
    ...
}

Указывается, что такая группировка и параллельная обработка являются плохим планом, и вместочто-то более раздельное:

void SummarizeData(...) {
    GetOldData( oldData, &numOldData );
    totalOldData = Sum( oldData, numOldData );
    PrintOldDataSummary( oldData, totalOldData, numOldData );
    SaveOldDataSummary( totalOldData, numOldData );
    ...
    GetNewData( newData, &numNewData );
    totalNewData = Sum( newData, numNewData );
    PrintNewDataSummary( newData, totalNewData, numNewData );
    SaveNewDataSummary( totalNewData, numNewData );
    ...
}

Я согласен, что второй подход легче читать и понимать, и предлагает более чистый код, по крайней мере, с моей точки зрения.Итак, мой вопрос: есть ли недостатки у второго подхода?Например, одна возможная проблема, о которой я мог подумать, связана с временными подключениями к базам данных:

void SummarizeData(...) {
    ...
    externalDataStore.open();
    externalDataStore.save(oldData, numOldData);
    externalDataStore.save(newData, numNewData);
    externalDataStore.close();
    ...
}

Этот первый подход завершит обе операции сохранения в одном цикле открытия / закрытия.Однако при втором подходе ...

void SummarizeData(...) {
    ...
    externalDataStore.open();
    externalDataStore.save(oldData, numOldData);
    externalDataStore.close();
    ...
    externalDataStore.open();
    externalDataStore.save(newData, numNewData);
    externalDataStore.close();
    ...
}

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

Извините за излишне длинный вопрос ...

Ответы [ 2 ]

1 голос
/ 26 августа 2011

Я еще не дошел до главы 10 в разделе «Завершить код» (еще несколько вечеров должны это сделать!), Но я думаю, что главное здесь - сгруппировать строки кода в логическом и легко читаемом виде, без ущерба для функциональности программы. Другими словами, очистите его и переставьте как можно больше, но остановитесь, как только оно начнет фактически влиять на поведение.

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

0 голосов
/ 02 сентября 2011

Мне было скучно, поэтому я попытался провести тест скорости в Python для проверки концепции, используя Sqlite (который, как я понимаю, не лучший способ сделать это).

Во-первых, базовый тест из 50 000итерации, открытие и закрытие соединения после каждой итерации.

#!/usr/bin/env python

import sqlite3

class Creature(object):
    legs = 0

    eyes = 'monocular'

    kind = ''

conn = sqlite3.connect(':memory:')

c = conn.cursor()
c.execute('''create table testtable
        (date text, legs text, eyes text, kind text)''')
conn.commit()
c.close()

for i in range(50000):
    c = conn.cursor()

    creature1 = Creature()
    creature1.legs = 5
    creature1.eyes = 'monocular'
    creature1.kind = 'mungy'
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature1.legs), creature1.eyes, creature1.kind))

    creature2 = Creature()
    creature2.legs = 3
    creature2.eyes = 'binocular'
    creature2.kind = 'thingy'
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature2.legs), creature2.eyes, creature2.kind))

    creature3 = Creature()
    creature3.legs = 3
    creature3.eyes = 'monocular'
    creature3.kind = 'pungy'    
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature3.legs), creature3.eyes, creature3.kind))

    conn.commit()
    c.close()

А теперь 50000 итераций, но без закрытия соединения.

#!/usr/bin/env python

import sqlite3

class Creature(object):
    legs = 0

    eyes = 'monocular'

    kind = ''

conn = sqlite3.connect(':memory:')

c = conn.cursor()
c.execute('''create table testtable
        (date text, legs text, eyes text, kind text)''')
conn.commit()
c.close()

c = conn.cursor()
for i in range(50000):

    creature1 = Creature()
    creature1.legs = 5
    creature1.eyes = 'monocular'
    creature1.kind = 'mungy'

    creature2 = Creature()
    creature2.legs = 3
    creature2.eyes = 'binocular'
    creature2.kind = 'thingy'

    creature3 = Creature()
    creature3.legs = 3
    creature3.eyes = 'monocular'
    creature3.kind = 'pungy'

    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature1.legs), creature1.eyes, creature1.kind))
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature2.legs), creature2.eyes, creature2.kind))
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature3.legs), creature3.eyes, creature3.kind))

    conn.commit()
c.close()

Результаты?

First method: Average 2.264s
Second method: Average 2.157s

Итак, это имеет значение, хотя и незначительное.

И вот оно у вас.

Определенно согласен с тем, что сказал Стефан.

...