Модульность WPF-приложений (или Использование IoC-контейнеров, часть 3)

Последнюю неделю (или даже чуть больше) мы занимаемся разбором кода пришедшего нам WPF-проекта, а также поиском и корректировкой архитектурных недоработок. Проекту где-то год-полтора, но работа над ним велась не слишком активно (долгое время — одним разработчиком), поэтому кодовая база не слишком велика.

Собственно, предыдущий топик родился как раз под влиянием беглого просмотра сложившейся ситуации. По прошествии недели мысли слегка улеглись, и хочется обобщить предложенные решения.

Итак, что у нас имеется? Допустим, есть модуль, который призван искать подключенные к компьютеру устройства — SD-карты с определенным содержимым, или приборы, подключенный по USB.
Как бы мы хотели видеть использование данного класса?

var detector = new DeviceDetector();
var devices = detector.Detect();

И если вторая строчка определяется контрактом класса и фактически так и выглядит, то вот конструктор класса DeviceDetector выглядит совсем по-другому:

public class DeviceDetector {
  public DeviceDetector(IComPortSearcher searcher,
                                IUsbValidator validator,
                                IDriveSearcher driveSearcher,
                                IDeviceValidator validator) {
  }
}
var devices = detector.Detect();

Continue reading

Простая кастомная ASP.Net MVC3-совместимая авторизация

Проблема — есть база пользователей с существующего проекта. Надо — авторизовать пользователей по этой базе из проекта на MVC3. Желательно минимумом усилий, но при этом с получением плюшек типа ограждения определенного функционала атрибутом [Authorize] от незарегистрированных :)

В гугле практически сразу натыкаешься на различные перегрузки MembershipProvider, но все примеры пугают своей монструозностью, обязательным использованием какой-нить-sql-compact и предоставлением возможности регистрации пользователей в придачу.

Если все это не требуется, а БД уже есть, или просто есть два-три пользователя, пароли которых можно просто захардкодить — то хочется получить всё максимально быстро. Этим мы и займемся.
Continue reading

Использование IoC-контейнеров, часть 2

Со времен прошлой записи про Inversion of Control, контейнеры таки плотно вошли и пустили корни в нашей повседневной жизни. В новом проекте он используется сплошь и рядом, да и при переписывании частей legacy-кода то и дело норовит внедриться.

Однако, используя контейнеры очень легко забыть о модульности и разделении областей видимости.
Как это обычно происходит: проект только начинается, пишутся первые корневые классы, появляется первый UI. При этом проект еще маленький и кажется, что все его части имеют очень много общего (так и есть на самом деле — мы ведь только начинаем). Мы решили использовать контейнер и при старте приложения все типы в нём сразу зарегистрировали.
Наступило счастье — любой класс мы можем с лёгкостью разрезолвить со всеми его зависимостями. Вроде бы всё хорошо.

Но с ростом появляются издержки. Поскольку всё регистрируется в одном месте — все классы во всех проектах публичные. Поскольку контейнер един — мы не задумываемся об обособленности отдельных проектов (всё равно всё успешно отрезолвится в рантайме).
Как следствие из этого — проблемы с пониманием из-за отсутствия абстрагированных регионов и проекты становится проблематично «выдернуть» из продукта и использовать отдельно (что, во-первых, часто пригождается, а во-вторых, помогает в проектировании).

Как «рецепт успеха» я бы рекомендовал всегда рассматривать проект (или группу проектов с единым назначением) как обособленную единицу, и всегда задумываться о его собственном внешнем интерфейсе (он, обычно, состоит из буквально одного-двух интерфейсов), а не отталкиваться от того, как он будет использован в конкретный момент в конкретном продукте.

Как следствие, каждый такой проект или группа проектов будут, скорее всего, иметь свой собственный контейнер, который упростит разработку конкретной области.

Использование IoC контейнеров. За и Против

//Написано в далеком апреле 2010-го года. Изначально опубликовано на хабре. В контексте следующей записи будет интересно вспомнить «как оно было год назад» и что изменилось с тех пор :)

В свете выхода новой версии Enterprise Library, одной из важнейших частей которой является IoC-контейнер Unity, лично я ожидаю всплеск интереса к теме IoC(Inversion of Control) контейнеров, которые, по сути, являются реализацией достаточно известного паттерна Service Locator.

В этом топике я хотел бы подискутировать на тему «правильного» использования таких контейнеров, а также предостеречь новичков от применения его «везде и всюду». Ну и просто интересующимся возможностями «новых технологий» тоже должно быть любопытно.

Предыстория проблемы

Continue reading

Адын-адын, тест-тест

Решил переехать на wordpress и собственный домен с blogspot’a, ибо и интерфейс у гугловского блогохостинга дурацкий, и адрес у меня там дурацкий и вообще глупо как-то постоянно говорить «что ты делаешь на этом говно-блогспоте», а самому сидеть там :)

В общем, буду потихоньку перетаскивать старые посты сюда и дописывать чего-нибудь нового. Тем более, что нового из мира EF и WPF ожидается прилично.

 

Краткий конспект по запуску MVC на Mono (Ubuntu)

Краткий конспект по проблемам, с которыми сталкивался разворачивая MVC3-сайт на Ubuntu с nginx и Mono. Пост «для себя» чтобы не забыть. В результате будем иметь наш ASP.Net MVC3 сайт работающий на Ubuntu-сервере с фронтэндом в виде nginx и моно запущенным как fcgi-server.

  1. Ставим последнюю версию Mono wget —no-check-certificate https://github.com/nathanb/iws-snippets/raw/master/mono-install-scripts/ubuntu/install_mono-2.10.sh когда выйдет следующая версия гуглить на тему install_mono.
  2. Скрипт запуска fcgi-сервера моно копируем в /etc/init.d, копируем monosites.conf. в /etc предварительно изменив в нём путь к папке, где будет лежать ваш MVC-проект (этот файл требуется monoserve’у, путь к нему прописан в нём же, при необходимости можно поменять).
  3. Настраиваем nginx. Насколько я представляю, это стандартная настройка с использованием fcgi. Пример конфигов factcgi_params и настройка конкретного сайта monosite (лежит в папке sites_enabled)
  4. Деплоим проект на сервер. Должна получиться следующая структура

    /
    — App_Code (копируем из проекта, если используем шареные хелперы)
    — Views (папка с вьюшками, копируем из проекта)
    — bin (папка с бинарниками. копируем из проекта)
    — Default.aspx (копируем из примера приложения, см. ниже)
    — Web.config (копируем из проекта)
    — Global.asax (копируем из проекта)

  5. В MVC проекте ставим CopyLocal=true для библиотек: System.Web.Helpers, System.Web.Mvc, System.Web.Razor, System.Web.WebPages, System.Web.WebPages.Razor, System.Web.WebPages.Deployment. Здесь важен не CopyLocal, а тот факт, чтобы они попали в папку bin на сервере.
  6. Копируем в папку bin файл Microsoft.Web.Infrastructure из установленной версии Mono (/opt/mono/lib/gac…). Если библиотеки пункта 2 должны быть Майкрософтовские, то эта должна быть Моновская!
  7. Стартуем моно: /etc/init.d/monoserve start и nginx /etc/init.d/nginx restart. Monoserve выдаст в консоль свои не очень понятные логи, но «взлетели» или нет разобрать можно :)
    На этом этапе всё уже должно работать.
  8. Если что-то не работает и непонятно, где ошибка — в установке моно или деплое проекта, то можно скопировать точно работающий проект в ту папку, куда вы деплоите. Перезапустить моно и решить дилему, кто же всё-таки неправ :)
  9. Ниже список возможных ошибок и немного кода
    Continue reading

Краткий конспект по старту с MVC

Дабы не забыть о свежедостигнутом в рамках MVC — законспектирую это здесь.

  1. НИКОГДА не называть параметры функций в контроллере «action» и «controller». Это запутывает маршрутизацию и приводит к ошибке An item with the same key has already been added.
  2. Для использования strongly-typed ActionLink, RenderAction, RenderPartial и прочего зареференсить Microsoft.Web.Mvc. Добавить @using во все вьюшки можно через Web.config и Views\Web.config
  3. Использование strongly-typed (строго типизированных) ссылок и рендерингов:
    @(Html.ActionLink<HomeController>(x=>x.Index(param1), «Текст ссылки»)) и
    @{Html.RenderAction<HomeController>(x=>x.Index(param1));}

    ActionLink обязательно заключать в круглые скобки, RenderAction и RenderPartial — в фигурные, иначе работать не будет

  4. Тестить контроллер — MvcContrib.TestHelper для тестирования редиректов, для тестирования возвращаемой модели кастовать ActionResult в ViewResult и проверять ViewResult.Model;
  5. Использование @helper внутри вьюшки: ссылка; для глобального использования создать папку App_Code и поместить вьюшку с хэлперами туда. воркэраунд для использования Html.ActionLink в App_Code-хэлперах: ссылка