0

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 );
    ...
}

少なくとも私自身の観点からは、2 番目のアプローチの方が読みやすく、理解しやすく、見栄えの良いコードを提供することに同意します。だから、私の質問は、2 番目のアプローチに欠点はありますか? たとえば、考えられる問題の 1 つは、データベースなどへの一時的な接続に関するものです。

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

この最初のアプローチでは、1 回のオープン/クローズ サイクルで両方の保存操作が完了します。ただし、2番目のアプローチでは...

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

操作ごとに接続を開いたり閉じたりする必要があります。これは無駄に思えますが、実際のパフォーマンスにどのように影響するかわかりません。

不必要に長い質問で申し訳ありません...

4

2 に答える 2

1

Code Complete の第 10 章にはまだ到達していませんが (あと数晩で終了するはずです!)、ここでの主なポイントは、プログラムの機能に影響を与えずに、論理的で読みやすい方法でコード行をグループ化することだと思います。. つまり、可能な限りクリーンアップして再配置しますが、実際に動作に影響を与え始めたらすぐに停止します.

あなたの例では、「時期尚早の最適化はすべての悪の根源である」ことを心に留めておく必要がありますが、すぐにもう一度接続を再開しようとしている場合は、接続を閉じるべきではないと安全に想定できると思います、これら 2 つのアクションは文字通り互いに打ち消し合うためです。原則として、簡単にするために、接続は最初に必要になる直前にのみ開き、最後に使用した直後に閉じる必要があります。

于 2011-08-26T15:05:58.357 に答える
0

私は退屈だったので、Sqlite を使用して Python で概念実証の速度テストを実行してみました (これは最善の方法ではないことがわかりました)。

まず、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()

そして今、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()

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

したがって、無視できるものではありますが、違いが生じます。

そして、あなたはそれを持っています。

しかし、ステファンが言ったことには間違いなく同意します。

于 2011-09-02T18:08:02.613 に答える