ASP.NET MVC и правильная архитектура веб-приложений

Добрый день, уважаемые веб-мастера. Сегодня я бы хотел обсудить архитектуру ASP.NET MVC приложений, в случае, если вы делаете простой сайт.

Небольшой дисклеймер. Я — джуниор (и то, в лучшем случае). А поэтому, всё, что написано ниже, может не быть не только хорошей архитектурой веб-приложения, но и являться bad practice.

В последнее время мне довольно часто приходится разрабатывать простые веб-сайты на основе стека технологий .NET Framework. Конечно, я использую для этого ASP.NET MVC фреймворк, как де-факто стандарт на сегодняшний день.

А вот на уровне Данных уже возможны варианты: существует довольно много вполне нормальных по качеству ORM, а поэтому возможен выбор. Я обычно выбираю либо Entity framework — продукт microsoft, либо NHibernate — порт популярной Java ORM. Ещё есть хорошая ORM — DataObjects.Net, но это платное энтерпрайз решение, которое вряд ли подходит для простых сайтов.

Из СУБД я использую обычно MsSQL, как нативную для MS. Хотя, наверное, данные ORM позволят вам использовать и какие-нибудь MySQL и PostgreSQL.

Теперь возникает вопрос, что дальше делать? В принципе, данные из БД мы уже можем легко достать, да и CRUD имплементирован. Пока я являюсь сторонником N-layer architecture. В связи с этим, буду обсуждать архитектуру приложения на основе трёхзвенной архитектуры.

В любом простом приложении, по моему мнению, должны быть такие слои, как Отображение (Presentation layer) — это стандартный ASP.NET MVC проект. Он должен получать запросы от клиентов в контроллерах, запрашивать данные у сервисов, и отдавать их клиентам.

Слой бизнес логики — это Domain. Тут, лично я, создаю бизнес-сущности, а-ля:

public class UserPhoto {
    public virtual long Id
    {
        get;
        set;
    }

    public virtual string Link
    {
        get;
        set;
    }

    public virtual User User
    {
        get;
        set;
    }
}

Кроме того, в Domain я создаю интерфейсы сервисов — источников данных. Например,

    /// <summary>
    /// Сервис для работы с Ролями
    /// </summary>
    public interface IRoleService
    {
        Role GetRoleByName(string name);
    }

Конечно же, будет замечательно, если вы в Domain опишите все ограничения на данные.

Третий слой в проекте — это инфраструктура. Тут необходимо реализовывать репозитории всех бизнес-сущностей. Данный слой сильно зависит от того, какую ORM вы используете.

Каждый слой я выделяю в отдельный проект. Также я создаю проект Services — его задача — это реализация всех интерфейсов, описанных в Domain. Затем, DI-контейнер разрешит нужные мне интерфейсы, используя данные имплементации.

Собственно, слова для программиста — это воздух. Поэтому, я предлагаю вам посмотреть на Best practices. Если вы используете NHibernate, то стоит серьезно изучить замечательный низкоуровневый фреймворк S#arp Architecture. Он аккумулирует в себе всё самое хорошее, и показывает, как нужно разрабатывать маленькие и средние по объему приложения.

Данный фреймворк, к сожалению, давно не обновляется. Поэтому, по умолчанию там ASP.NET MVC 3. Однако добрые люди обновили все зависимости (в том числе и ASP.NET до MVC 5) и выложили это дело на гитхаб.

Если ваш выбор — это Entity framework, то готового фреймворка, к сожалению, нет (по крайне мере я его не знаю). Однако есть крайне интересный проект SocialGoal на гитхабе — бесплатная небольшая социальная сеть, в котором как раз таки реализованы все те вещи, о которых я говорил. Думаю, тот проект можно брать, как основу.

Кстати, этот проект построен на всём самом современном: ASP.NET MVC 5, EF 6 Code First, AutoMapper, Autofac и TDD. Поэтому, данный репозиторий отлично подойдёт для обучения.

Ещё одно примечание. SocialGoal построен на основе http://efmvc.codeplex.com/ — можно посмотреть и в эту сторону.

Буду рад, если вы напишите свои архитектурные решения для простых сайтов на ASP.NET MVC в комментариях.

Категории: Веб-мастеринг Программирование

Метки: ,


  • Ivan Artemov

    Плохой пример с SocialGoal

    Когда в коде видишь такое:

    public interface IRepository where T : class
    {
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
    …….
    }

    то невольно задумываешь о квалификации человека, который пишет подобное.
    Похоже на поделку чью-то.