Я сделал небольшое приложение с, как мне кажется, нормальной многослойной архитектурой. https://github.com/mirypoko/Astoms Подскажите пожалуйста, может я что-то делаю не так? Может есть какие-то более хорошие подходы.
Есть несколько вопросов:
Не слишком ли много бизнес логики в моих контроллерах?
Имеет ли смысл делать статические репозитории и статический UnitOfWork, которые будут использовать ссылку на объект DbContext для работы? Или лучше чтобы они были объектами?
Если ли смысл в методе Dispose класса UnitOfWork? Я сделал его по примерам из интернета, но Dispose у меня нигде не используется. Если его нужно использовать, то где и зачем?
Как я понял, я использую антипаттерн Generic-repository. Чем плохим это может грозить в будущем?
У приложений всегда должен быть только один контекст базы данных или сколько угодно? (имею в виду как будет грамотнее с точки зрения проектирования приложений)
Ответ
В данный момент существует множество подходов к созданию архитектуры MVC приложений (Domain Driven Design, 3d-layered architecture, onion structure, etc).
Мой любимый подход это 3х уровневая архитектура и вот почему:
Позволяет легко избавиться от зависиомтей используя Inversion of Control
Каждый из уровней отвечает за свои задачи, что позволяет придерживаться принципа Single responsibility даже на уровне слоя.
Приложение ASP.NET MVC с этим подходом выглядело бы так:
Data layer - библиотека, которая организовывает связь с базой данных, в неё входят UoW, Repository pattern, EF если имеется и Data models
Bussiness layer - библиотека отвечающая за сервисы, бизнес логику и DTO (data transfer objects которые связывают Data Models и View Models)
Presentation layer - собственно сам MVC, сюда входят ViewModels, View, Controllers, конфигурация IoC и т.д.
Благодаря такой архитектуре изменения в одном уровне не повлекут за собой огромных изменений (а при правильном построении SOLID вообще не изменят другие слои).
Теперь по поводу реализации и вопросов:
Контроллеры должны быть по принципу as thin as possible и любая бизнес логика в них говорит о том что реализацию можно улучшить и всю логику можно и нужно выносить в сервисы. В вашей реализации присутствует обработка изображений, которую по хорошему следует вынести в отдельный сервис назвав его ImageManipulationService и убрать из контроллеров #helpers
Любую статику очень сложно покрыть тестами в будущем, лучше всего придерживаться реализации этих паттернов как объектов - в будущем будет намного легче поддерживать приложение.
Интерфейс IDisposable специально был разработан для высвобождения ресурсов, которые не будут уничтожены Garbage Collector`ом (в основном это касается unsafe кода), в реализации UoW считается хорошей практикой высвобождать DbContext перед уничтожением самого UoW, так что паттерн реализован хорошо.
Использование Generic Repository довольно распространенная практика и это намного лучше чем писать под каждую сущность новый объект репозитория. Не вижу никаких проблем использовать этот паттерн.
У приложения может быть несколько контекстов базы данных в случае если приложение использует несколько БД одновременно. На практике такое случается крайне редко и если это вопрос по поводу реализации общего интерфейса для DbContext то это скорее overengeenering чем хорошая практика.
PS. Под Generic Repository хорошо подходит реализация Generic UoW:
public interface IUnitOfWork : IDisposable
{
T GetRepository
public class UnitOfWork : IUnitOfWork
{
private Dictionary
public UnitOfWork() : this(new AppContext())
{
}
public UnitOfWork(IDbContext dbContext)
{
_dbContext = dbContext;
_repositories = new Dictionary
///
return (T)_repositories[nameof(T)];
}
///
///
private void Dispose(bool disposing)
{
if (disposing)
{
if (_dbContext != null)
{
_dbContext.Dispose();
_dbContext = null;
}
}
}
}
Комментариев нет:
Отправить комментарий