Aggregation root не только в контексте БД-приложений (и граничные значения SOLID’a)

Концепции DDD, которые я начал практиковать относительно недавно, напомнили о принципе корня агрегации, который на БД-сущности очень хорошо ложится.

Однако про корни агрегации не стоит забывать и в тех модулях, которые с базой данных никак не связаны. Этот казалось бы очевидный момент несложно упустить, «слепо» следуя SOLID-принципам.
Continue reading

Generic-типы — это просто :)

    internal class ChooseServerStage : ActStageBase
    {
        public ChooseServerStage(FinderWrapper<RegionFinder<PixelCounterComparer<whitelettercolorpixelcriteria>>> finder)
            : base(finder)
        {
        }
    }

Дженерик-тип тройной вложенности в конструкторе :) Только что написал подобную конструкцию в своем собственном коде.
Continue reading

Session/context management в настольных приложениях

Когда в сети говорят об ORM в .net — очень часто в качестве сферы применения «по умолчанию» рассматривается ASP.Net (и MVC в частности).
Происходит это, как мне кажется, потому, что именно веб — среда наиболее динамичная, открытая и быстро подхватывающая новые веяния, вследствие полной свободы в технических решениях. В случае, к примеру, Win Forms приложений переход со второго фреймворка на 4-ый — сложнейший шаг (апдейт должен затронуть всех пользователей, а у некоторых, может быть, еще win2000 :)), а для ASP.Net разработчиков проапгрейдить сервер, обычно, не проблема.
Еще одна причина может быть в том, что «принципы работы» в случае веба типичны, и рабочий цикл мал — пришел запрос, сгенерили ответ, отдали клиенту, вернулись в начальное состояние. Следовательно и подходы, применяемые одной компанией, легко адаптируются и в другой.
Desktop-приложения же часто очень велики, с длинным циклом разработки и, обычно, с устоявшимися внутри компании методиками работы, которые не всегда легко переносимы.

В этом посте я хотел бы рассказать об одной из специфических трудностей, с которыми можно столкнуться при работе с ORM в настольных приложениях, а именно: управление контекстом/сессией.
Continue reading

Простой способ обезопаситься от CSRF в ASP.Net MVC

Наверное, все, кто занимается веб-разработкой слышали о CSRF-уязвимостях (читается sea-surf). Если быть кратким, то если у вас на сайте есть ссылки вроде http://mysite.ru/Articles/Delete/24, по которой удаляется статья с 24-ым айдишником (естественно, с проверкой прав доступа), то если авторизовавшийся на вашем сайте админ зайдет на какой-нибудь зловредный сайт, в котором подсонут яваскрипт вроде

window.location.href = "http://mysite.ru/Articles/Delete/24"

то статья с вашего сайта успешно удалится. Конечно, использовать такие уязвимости достаточно сложно, и наврядли атаку подобного типа проведут на сайт с посещаемостью в 1-2 тысячи человек. Но если вы планируете раскрутиться до уровня твиттера… :)
Впрочем, оставлять лазейки в безопасности не хочется, даже если сайт пишется для «внутренних целей», что уж говорить про продакшен.

Тем более, что MVC3 позволяет с лёгкостью таких атак избежать.
Continue reading

Слой доступа к данным в .net приложениях

При разработке приложений, работающих с базой данных, неизменно встает вопрос проектирования слоя доступа к этим самым данным. Использование «чистого» ADO.Net в рамках больших и сложных приложений рассматривается всё реже, и использование ORM становится уже стандартом де-факто.

Однако и после выбора ORM вопросы проектирования не заканчиваются — встает проблема собственно организации слоя доступа к данным. Здесь есть несколько ставших уже классическими подходов:
Continue reading

Portable Areas и T4MVC

В комментариях к кросспосту предыдущей статьи на хабрахабре появились вопросы о применимости T4MVC к модулям с «выделенными областями».
Это послужило для меня хорошим поводом попробовать T4MVC и осознать всю его мощь. По ходу ознакомления T4MVC был слегка модифицирован для поддержки «выделенных областей» (portable areas) и данные изменения были успешно включены в проект на codeplex автором T4MVC Дэвидом Эббо.

Ниже — детали интеграции T4MVC и Portable Areas.
Continue reading

Portable Areas как вариант модульности в MVC

Один из первых вопросов, которым я задался после знакомства с азами технологии MVC3, это способ выделения и повторного использования функционала в нескольких веб-проектах.
В WPF или WinForms все просто и понятно — обособленный функционал изолируется в модуль, модуль компилируется в библиотеку, библиотека — подключается к проекту и повторно используется. Нужно лишь грамотно изолировать модули, и всё будет хорошо.

В MVC всё не так просто, если «обособленный функционал» — это набор контроллеров и вьюшек, реализующих, допустим, гостевую книгу, то просто так вынести их в отдельный модуль нельзя — MVC просто не найдет ваши контроллеры в соседних библиотеках.

Однако решение, конечно, есть, и его нам предлагает небезызвестная библиотека MvcContrib — open-source проект, неаффилированный Майкрософтом.
Continue reading

Модульность 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. При этом проект еще маленький и кажется, что все его части имеют очень много общего (так и есть на самом деле — мы ведь только начинаем). Мы решили использовать контейнер и при старте приложения все типы в нём сразу зарегистрировали.
Наступило счастье — любой класс мы можем с лёгкостью разрезолвить со всеми его зависимостями. Вроде бы всё хорошо.

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

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

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