0

以下のコードを見てください。

    Public Sub MassDelete()
        Dim objCommand As SqlCommand
        Dim objCon As SqlConnection
        Dim objDR As SqlDataReader
        Try
            Dim _ConString As String = "Data Source=IANSCOMPUTER;Initial Catalog=Test5;Integrated Security=True;MultipleActiveResultSets=true"
            objCon = New SqlConnection(_ConString)
            Using objCon
                    objCommand = New SqlCommand("SELECT * FROM Person WHERE StartDate <= dateadd(-6,year," & Now & ")")
                objCommand.Connection = objCon
                Using objCommand
                    objCon.Open()
                    objDR = objCommand.ExecuteReader
                    Do While objDR.Read
                        'Send ID over web service
                        'Send email to person
                        'Add log entry to log file
                    Loop
                    objDR.Close()
                End Using
            End Using
        Catch ex As Exception
            Throw
        Finally

        End Try

前の開発者からのこのようなコードがたくさんあります。つまり、人、車両、アカウントなどのテーブルをループし、数千、場合によっては数百万のレコードに対してアクションを実行する 1 つの関数です。上記の場合、開始日から6年後に削除されます。while ループの反復ごとに 3 つのアクションがあります。つまり、Web サービス経由で ID を送信し、個人に電子メールを送信し、ログ エントリをログ ファイルに追加します。問題のシステムの開発を続けながら、このコードをリファクタリングしようとしています。

MassDelete 関数ですべての作業を行うのではなく、Email、WebService、および Log に対して異なるクラスが必要であると考えています。作業はクラス間で分散されます。たとえば、電子メールは Email クラスから送信されます。ループの反復ごとに WebService、Email、および Log のオブジェクトを作成し、それらのインスタンス変数を使用することに制限はありますか?

4

1 に答える 1

1

オブジェクトの作成は安価ですが、つまり、ループごとに新しいオブジェクトを作成しても、全体的なパフォーマンスへの影響はありません (コンストラクターの作業量に依存します) - 新しいオブジェクトは、意味的に正しい/意味がある場合にのみ実行する必要があります。

この場合、特定のサービス呼び出しに渡されるだけのデータ(Person レコードなど) からサービスを分離しておくことをお勧めします。私は実際にはVB.NETを知りません(C#を使用しています)ので、必要に応じて構文を調整してください。

' Note that the services are bound to some things - but NOT people
' I recommend using DI/IoC (Dependency Injection)
' Also the Logger is generally a larger application-wide service
Var mailer = New EmailService(SMTPServerString, SMTPTimeout)
Var ws = New WebService(WSEndpoint)
Var log = New LoggerService()
Var objCon = OpenConnection()

Using objCon
    Var objCommand = objCon.CreateCommand(..);
    Using objCommand
        Var objDR = objCommand.ExecuteReader
        Do While objDR.Read
            ' Person different per loop
            Var person = New Person(objDR) 
            ' But services are the same and are not "bound" to a person
            ws.RecordDelete(person.Id)
            mailer.Send(person.Email, Subject, Message)
            log.Log(Log.Information, "Deleted person: " & person.Id)
        Loop
    End Using
End Using

もちろん、このコードはまだ耐障害性や配布可能性が高くありません。メッセージ キュー (AMPQ など) は検討する価値があるかもしれません..

于 2013-03-28T22:27:48.280 に答える