WebアプリケーションでBLL、PL、DALを分離する
-
26-10-2019 - |
質問
複数のプレゼンテーションレイヤーを持つことができるWebアプリケーションを開発することができました。現在はWeb上にありますが、すぐにデスクトップやその他のプラットフォームにあります。それで、私はそれを最善の方法を検索しました。層状のアプローチを使用する方が良いことがわかりました。
私は、異なるPLSがアクセスできるWebサービスとしてBLLを持つことを考えています。 BLLは、データ固有の操作についてDALにアクセスします。これまでのところ非常に良いですが、WebアプリにASP.NET MVCを使用することを考えていました。 「コントローラー」には基本的にビジネスロジックが含まれているため、私は少し混乱しています。それは良い選択肢ですか? MVCと上記のレイヤーを使用して同じパスをたどると、私のコントローラーは必ずしもBLLを含めることはできませんが、ちょっとダミーだけです。
それはそれを行う正しい方法ですか?
解決
これらは推奨されるレイヤーです:
プレゼンテーション(MVC、WPFなど):プレゼンテーションロジックのみを含む(ビジネスロジックを含むことはありません)コントローラーは、アプリケーション/サービスレイヤーとの通信のみを調整する通信のみを処理します。
分散サービス(リモートファサード):多くのクライアントがいるので、それらのいくつかはWindowsアプリであり、他のクライアントはWebアプリであるため、ビジネスレイヤーを消費者に公開するリモートサービスレイヤー(WCFサービスまたはWebサービス)を作成することをお勧めします( DTOSを送信して受信することをお勧めします。
アプリケーションレイヤー:ドメインレイヤーとの通信を処理するレイヤー、および調整トランザクションロジックおよびテクニカルサービス。DTOを使用している場合は、ドメインオブジェクトをDTOに変換し、その逆も同様です。
ドメインレイヤー:エンティティとバリューオブジェクトが含まれます。これは、データとロジックをカプセル化するオブジェクト指向ドメインオブジェクトの観点から設計されたビジネスロジックのコアです。リポジトリパターンを使用する場合は、リポジトリインターフェイスを含めることもできます。単一のエンティティに適合しないロジックのドメインサービス。
データアクセス:NhibernateやEFなどのORMを使用して、エンティティをデータベーステーブルにマッピングするためのデータアクセス手法を使用します。
インフラストラクチャ /共通:ロギングなどのインフラストラクチャコードとクロスカットテクニカルサービス
私は各レイヤーについて小さな例を挙げようとします:仮説的な不完全な例はあなたが発注書をアクティブにしたいと言っています
プレゼンテーションレイヤー(MVC):
public class PurchaseOrderController
{
public ActionResult ActivateOrder(int id)
{
var response = _orderManagementService.ActivateOrder(id); // Call distributed service (Web Service)
if(response.Succeed)
return new SuccessActionResult();
else
return new FailedActionResult(response.Reason);
}
}
分散サービスレイヤー(Webサービス):
public class OrderManagementWebService : IOrderManagementService
{
private readonly IOrderExecutionService _orderService;
public OrderManagementWebService(IOrderExecutionService orderService)
{
_orderService = orderService; // Order Service from application service
}
public ActivationResult ActivateOrder(int id)
{
var response = _orderService.ActivateOrder(id); // Call the application layer to execute the logic
if(
}
}
アプリケーションレイヤー:
public class OrderExecutionService : IOrderExecutionService
{
private IOrderRepository _orderRepository;
public OrderExecutionService(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
public ActivationResult ActivateOrder(int id)
{
var order = _orderRepository.GetById(id); // Get the order from repository
try
{
order.Activate(); // Call business logic inside the order entity
return new ActivationResult { Success = true } ;
}
catch(ActivationException ex)
{
LogFactory.GetLog().Exception(ex); // Call log from infrastructure layer
return new ActivationResult { Success = false, Reason = ex.Message } ;
}
}
}
ドメインレイヤー:
public class PurchaseOrder : Entity
{
// Properties and fields (Data)
public int Id { get; private set; }
public Customer Customer { get; private set; }
// Methods (contains business logic)
public void Activate()
{
if(Customer.IsBlacklisted)
throw new InvalidCustomerException(...);
if(_lineItems.Count == 0)
throw new NoItemsException(...);
this.SetStatus(OrderStatus.Active);
.....
}
}
リポジトリ(データアクセスレイヤー):
public class OrderRepository : IOrderRepository
{
public PurchaseOrder GetById(int id)
{
// data access code to access ORM or any data access framework.
}
}
インフラストラクチュ:
public class Logger : ILogger
{
public void Exception(Exception ex)
{
// write exception to whatever
}
}