はい、あなたの質問は、ロジックをレイヤーに分離する非常にクリーンな方法を示しています。PersonBLL
クラスはビジネス レイヤーの一部になり、クラスPersonDAL
はデータ アクセス レイヤーの一部になり、Person
クラスはデータ転送オブジェクト (DTO) レイヤーの一部になります。これは、レイヤーを分離するための非常に一般的な方法であり、多くの状況でうまく機能します。
私の唯一の推奨事項は次のとおりです。
- 独自のクラス ライブラリ プロジェクトではない場合でも、各レイヤーを独自の名前空間に配置する必要があります。
- ビジネス層からメッセージ ボックスを表示しないでください。デモンストレーションの手段としてこれを行っただけだと思いますが、念のため、言及する必要があると思いました。メッセージ ボックスの表示は、UI レイヤーの一部である必要があります。たとえば
PersonBLL.getPersonByID
、Windows サービスまたは Web サービスから呼び出している場合、メッセージ ボックスを表示することはまったく不適切です。
- 通常、すべてのメソッドはキャメルケースではなくパスカルケースです。プライベート メソッドをキャメル ケースにすることを好む人もいますが、パブリック メソッドをキャメル ケースにするべきではないことは確かです。
- 依存性注入手法 (DI) を使用して、データ アクセス オブジェクトをビジネス オブジェクトに注入することを検討してください。
依存性注入
これを DI 手法で行う方法の例を次に示します。
Public Class BusinessFactory
Public Function NewPersonBusiness() As IPersonBusiness
Return New PersonBusiness(New PersonDataAccess())
End Function
End Class
Public Class PersonBusiness
Implements IPersonBusiness
Public Sub New(personDataAccess As IPersonDataAccess)
_personDataAccess = personDataAccess
End Sub
Private _personDataAccess As IPersonDataAccess
Public Function GetPersonByID() As PersonDto Implements IPersonBusiness.GetPersonByID
Return _personDataAccess.GetPersonByID()
End Sub
End Class
Public Interface IPersonBusiness
Function GetPersonByID() As PersonDto
End Interface
Public Interface IPersonDataAccess
Function GetPersonById() As PersonDto
End Interface
Public Class PersonDto
Private _name As String
Private _age As Integer
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Public Property Age() As Integer
Get
Return _age
End Get
Set(ByVal value As Integer)
_age = value
End Set
End Property
End Class
このようにすると、多くの利点があります。複数の交換可能なデータ アクセス レイヤーの実装を使用できるため、より柔軟になります。また、ビジネス クラスの単体テストを行う場合は、偽のデータ アクセス オブジェクトを挿入できます。DI 設計は、バグのあるスパゲッティ コードにつながる多くのトラップを回避します。
DI では、通常、依存オブジェクトを具象型としてではなく (たとえば、IPersonDataAccess
ではなくPersonDataAccess
) インターフェイスとして要求することをお勧めします。そうするのは少し面倒かもしれませんが、すぐに慣れます。多くの場合、その時点でクラスごとに 1 つのインターフェイスを作成するため、クラスと同じコード ファイルにインターフェイスを配置すると便利です。したがって、たとえば、PersonBusiness.vb にはPersonDataAccess
クラスとIPersonDataAccess
インターフェイスの両方が含まれます。
依存関係にクラスではなくインターフェイスを使用することが重要な理由は 2 つあります。
設計が柔軟であることを保証します。あらゆる種類の具体的な実装を作成できるように、依存関係の型のすべてのパブリック メンバーをオーバーライドできるようにする必要があります。これを行う方法は他にもあります。たとえば、クラスIPersonDataAcess
内のすべてのパブリック プロパティとメソッドを修飾子でマークするだけでインターフェイスの作成をスキップできますが、それを強制するものは何もありません。いつもそうするのを覚えていたとしても、あなたのコードで作業している他の誰かがそうすべきだと知っているとは限りません。PersonDataAccess
Overrideable
DI は、コードがテスト可能であることを確認するための最良のツールであるため、単体テストと結び付けられることがよくあります。単体テストでは、依存関係の型のメンバーをオーバーライドできることが特に重要です。これにより、単体テストを適切に実行するために必要な方法で機能する「偽の」オブジェクトを作成できます。これらの「偽の」オブジェクトはモックと呼ばれます。
依存関係が何であるかについて、より技術的に正直になります。PersonDataAccess
実際には、依存関係が実際にクラスのインスタンスであると言っているわけではありません。実際には、依存関係は、たまたま同じパブリック インターフェイスを持つオブジェクトです。クラスを要求することで、特定の実装が必要であることを暗示していますが、これは嘘です。適切に設計した場合は、インターフェースが同じであることのみを気にするため、インターフェース自体のみを要求することで、指定する意味を正確に指定しています:)