Разделение BLL, PL и DAL в веб-приложении
-
26-10-2019 - |
Вопрос
Мне поручили разработать веб-приложение, которое может иметь несколько уровней представления, в настоящее время оно находится в Интернете, но вскоре появится на настольных компьютерах и других платформах.Поэтому я стал искать, как это сделать лучше всего.Я обнаружил, что лучше использовать многоуровневый подход.
Я думаю использовать BLL в качестве веб-сервиса, к которому могут иметь доступ разные PL.BLL будет иметь доступ к DAL для операций с конкретными данными.Пока все хорошо, но я подумывал об использовании ASP.NET MVC для веб-приложения.Теперь я немного сбит с толку, потому что «контроллеры», по сути, содержат бизнес-логику, верно.Это хороший вариант?Если я пойду по тому же пути, используя MVC и вышеупомянутые уровни, мои контроллеры не обязательно будут содержать BLL, а будут всего лишь своего рода манекенами.
Правильный ли это способ сделать это?
Решение
Рекомендуемые слои:
Презентация (MVC, WPF, что угодно):содержит только логику представления (никогда не включает бизнес-логику), контроллер управляет только связью с уровнем приложений/сервисов для координации связи.
Распределенные сервисы (удаленный фасад):поскольку у вас будет много клиентов, некоторые из них будут приложениями Windows, а другие — веб-приложениями, рекомендуется создать уровень удаленного обслуживания (службы WCF или веб-службы), который предоставляет потребителям бизнес-уровень (предпочтительно отправлять и получать DTO).
Уровень приложения:уровень, который управляет связью с уровнем домена и координирует логику транзакций и технические услуги, а если вы используете DTO, он переводит объекты домена в DTO и наоборот.
Слой домена:содержит сущности и объекты значений. Это ядро бизнес-логики, разработанное с точки зрения объектно-ориентированных объектов предметной области, инкапсулирующих данные и логику.он также может содержать интерфейсы репозитория, если используется шаблон репозитория.и доменные службы для логики, которая не умещается в единую сущность.
Доступ к данным:использование ORM, такого как NHibernate или EF, или любых других методов доступа к данным для сопоставления сущностей в таблицах базы данных.
Инфраструктура/Общее:инфраструктурный код и сквозные технические услуги, такие как ведение журналов
Я попытаюсь привести небольшой пример каждого слоя:гипотетический неполный пример: вы хотите активировать заказ на покупку
Уровень представления (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);
}
}
Уровень распределенного сервиса (веб-сервис):
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
}
}