n層へのリファクタリング
-
03-07-2019 - |
質問
私は、DAOを使用するvb6プログラマーです。以下は、解き放つことができる典型的なコードの例です。
Sub cmdMultiplier_Click() 'Button on form, user interface '
dim Rec1 as recordset
dim strSQL as string
strSQL = "select * from tblCustomers where ID = " & CurrentCustomerID 'inline SQL '
set rec1 = GlobalDataBase.openrecordset(strSQL) ' Data access '
if rec1.bof <> true or rec1.eof <> true then
if rec1.fields("Category").value = 1 then
PriceMultiplier = 0.9 ' Business Logic '
else
priceMultiplier = 1
end if
end if
End Sub
上記がCRUDアプリケーションの完全なソースコードであるふりをしてください。 私はこのデザインが悪いことを知っています。すべてが混同されています。理想的には、ユーザーインターフェース、ビジネスロジックの3つの異なるレイヤーが必要です。 およびデータアクセス。なぜこれが望ましいのかはわかりますが、それがどのように行われるのかわかりません。 そのため、このような分離が優れている理由は完全にはわかりません。 誰かが上記をばかげてリファクタリングできるなら、私はずっと先に行くと思います 簡単な例を3層に分けます。
解決
簡単な例、はい、しかしすべての基本的な要素があります-それらは3つの異なるクラスに属しているだけです(以下を参照)。この主な理由は、「懸念の分離」です。つまり、GUIはGUIの事柄にのみ関係し、Biz Logicレイヤーはビジネスルールにのみ関係し、データアクセスレイヤーはデータ表現にのみ関係します。これにより、各レイヤーを独立して維持し、アプリケーション間で再利用できます。
'in Form class - button handler
Sub cmdMultiplier_Click()
PriceMultiplier = ComputePriceMultiplier(CurrentCustomerId)
End Sub
'in Biz Logic class
Function ComputePriceMultiplier(custId as Integer) as Double
Dim cust as Customer = GetCustomer(custId)
if cust.Category = 1 then 'please ignore magic number, real code uses enums
return 0.9
end if
return 1
End Function
'in Data Access Layer class
Function GetCustomer(custId as Integer) as Customer
Dim cust as Customer = New Customer 'all fields/properties to default values
Dim strSQL as String = "select * from tblCustomers where ID = " & custId
set rec1 = GlobalDataBase.openrecordset(strSQL) ' Data access '
if rec1.bof <> true or rec1.eof <> true then
cust.SetPropertiesFromRecord(rec1)
end if
return cust
End Function
[「実際の」アプリケーションは、現在の顧客をキャッシュし、顧客クエリのための定数またはストアドプロシージャなどを持ちます。簡潔にするため無視されます]
これをボタンハンドラーの元のすべての例と比較してください(この方法は非常に簡単なので、VBコードでは驚くほど一般的です)-別のアプリケーションで価格乗数ルールが必要な場合は、そのアプリケーションのボタンハンドラーにコードをコピー、貼り付け、編集する必要があります。これで、同じビジネスルールを維持するための2つの場所と、同じ顧客クエリが実行される2つの場所があります。
他のヒント
ボタンの目的は何ですか?
最初のステップは次のとおりです。
- データベースにアクセスする部分を抽出します。 (警告:先にエアコード)
function getCustomer(CurrentCustomerID as Long)
strSQL =&quot; select * from tblCustomers where ID =&quot; &amp; CurrentCustomerID set rec1 = GlobalDataBase.openrecordset(strSQL) 結果= 1
if rec1.recordcount&gt; 0 then getCustomer = rec1 他に getCustomer = false エンディフ 終了関数
- ビジネスロジック関数を作成します:
function getCustomerDiscount(longとしてのcustomerID)
customer = getCustomer(customerID)
res = 1 顧客なら customer(&quot; category&quot;)= 1)の場合 res = .9 エンディフ endif
getcustomerdiscount = res
関数の終了
- 次に、ボタンを変更します:
Sub cmdMultiplier_Click() pricemultiplier = getcustomerdiscount(currentcustomerid) 終了サブ
通常、ユーザーが発生したイベント(この場合はボタンクリック)にUIコードを応答させます。
その後、プログラムの設計方法に大きく依存します。最も基本的な設計は、Customerインスタンスを参照することで、乗数プロパティが含まれます。 顧客オブジェクトは、DALのデータから取り込まれます。
UIの検証はUIレイヤーに、ビジネス検証ルールはビジネスオブジェクトに、そしてDALが永続レイヤーになります。
これは非常に基本的な擬似コードの例です:
btnClick
Dim Cust as New Customer(ID)
multplr = Cust.DiscountMultiplier
End Click
Class Customer
Sub New(ID)
Data = DAL.GetCustomerData(ID)
Me.Name = Data("Name")
Me.Address = Data("Address")
Me.DiscountMultiplier = Data("DiscountMultiplier")
End Sub
Property ID
Property Name
Property Address
Property DiscountMultiplier
Return _discountMultiplier
End
End Class
Class DAL
Function GetCustomerData(ID)
SQL = "Paramaterized SQL"
Return Data
End Function
End Class
リファクタリングの方法を知っているのは良いことです。これから、レイヤーを分離する方法がわかります。
ただし、同時に使用しているツールをアップグレードする方が時間を節約できると思います。 VB.Netでそれを行うことを考えていますか?
既存のコードベースを維持する方法は、VB.NetでデータレイヤーとBRをコーディングすることです。次に、COMインターフェイスを介してBRを公開します(これはプロジェクトのチェックボックスオプションです)。その後、現在のインターフェースから新しいBRを使用できます。
BRとDALがすべて完了すると、完全に新しいプラットフォームに一歩近づきます。