INPC Framework

Сложность 100

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

Некоторые библиотеки по реализации интерфейса предлагают в «полезную нагрузку» IoC контроллеры и перехватчики в стиле АОП.

Хотя до недавнего момента я использовал часто Kind Of Magic для решения этой проблемы, я неоднократно сталкивался с тем, что люди в свойства запихивают огромный функционал и этим отрицают целесообразность использования средств в духе Magic. Либо же начинают рассказывать о том, что должен быть полный контроль кода – все надо писать руками.

Относительно давно были анонсы о фремворке от Sharpcrafters, но я как-то пропускал их в силу разных причин и загруженности, но наконец дошли руки и я хочу вам рассказать о PostSharp Domain Toolkit, он же INPC Framework.

Коротко о главном

Распространяется PostSharp Domain Toolkit c помощью NuGet пакета. Установить его можно выполнив команду:

Install-Package PostSharp.Toolkit.Domain

После чего установится как сам тулкит, так и PostSharp. Можно начинать работу.

Самый простой и общий сценарий будет заключатся в добавлении атрибута NotifyPropertyChanged к вашей вьюмодели. Всё. Больше ничего делать не надо. Автоматически «магическим» образом будут обработано подавляющее большинство всех сценариев работы в среднестатистическом приложении.

Подробнее

Self-Tracking Objects

Сложность 400

Долго думал как можно по-русски кратко и красиво назвать статью, но не придумал ничего хорошего, поэтому оставляю как есть на английском, так как это наиболее ёмко и в полной мере отражает характер тех объектов, что мы будем описывать. А под описание сегодня у нас попадают объекты, которые могут отслеживать изменения в себе на уровне полей/свойств.

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

Подробнее

Ненавистный INotifyPropertyChanged

Да, уже из названия видно мое отношение к интерфейсу INotifyPropertyChanged и к его явной реализации в проекте. Я покрываюсь мурашками, и меня бросает в дрожь только при одном виде такого кода:

Какая растрата места на экране, какая колоссальная неэффективность написания кода, какая хрупкость в работе. Передача строковых переменных не может быть не хрупкой.

А когда таких свойств прописано с десяток и все это обернуто в регион (#region), то взгляд стекленеет, становится безжизненным и мозг отказывается верить в реальность происходящего. Конечно, самое большое зло от такого подхода – потеря времени на написание и на чтение.

Более того, это чистый инфраструктурный код, который не должен попадаться на глаза в логике приложения, только если специально его искать. Реализация INotifyPropertyChanged прямой и явный кандидат на реализацию в рамках аспектного-ориентированного программирования.

К сожалению, при разработке пользовательского интерфейса на WPF такая реализация «в лоб» встречается до сих пор сплошь и рядом. Не далее чем неделю назад вычищал такой код из рабочего проекта. Я бы порадовался за трудолюбие и усидчивость разработчиков пишущих такой код, но я склонен думать, что программист должен быть ленивым. В хорошем смысле. Так что лучше потерять немного времени на настройку и потом быстро-быстро все сделать. Далее я опишу 4 более-менее различных подхода к решению данной проблемы.

Подробнее

PostSharp. Безопасность полей класса

И снова речь пойдет о PostSharp! =) Сегодня я хочу рассказать об аспекте OnFieldAccess (или в версии 2.0 LocationInterceptionAspect), который позволяет держать контроль над использованием свойств и полей класса. В прошлых статьях я рассказывал о применении аспектов на вызовы методов и о задачах, которые могут быть решены с их помощью. В целом, все те же задачи применимы и к полям: логирование изменения значений полей, защита доступа по ролям. Кроме этого можно организовать защиту полей от записи, декларативную проверку значений, уведомление других объектов об изменении значений.

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

Так же, в этой статье я рассмотрю такую возможность PostSharp, как проверка возможности применения аспекта на этапе компиляции. Я считаю, что это замечательная возможность, которой не стоит пренебрегать в дальнейшем. Для кого-то это может даже стать решающим моментом в применении данного продукта. Я знаю таких людей, которые ни за что не будут пользоваться продуктом, который не будет их строго ограничивать, а тут они имеют возможность написать себе такие ограничения и радоваться жизни. Да и в случае дистрибуции третьим сторонам вашей библиотеки это будет полезно.

Подробнее

PostSharp. Безопасность

Продолжаем подробный разговор о аспекте OnMethodBoundary.  Данный аспект применяется, когда у вас есть доступ к исходным кодам метода и вы хотите отслеживать события начала вызова метода, конец вызова, исключение и успешность завершения.  Все это делается переопределением методов OnEntryOnExitOnException и OnSuccess соответственно.

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

Security

При создании более-менее сложных программных продуктов, часто требуется определять несколько ролей для работы с программой. В самом минимальном случае это администратор и пользователь. Для такого набора ролей можно как-то вывернутся по-простому, например, разграничить экраны для этих ролей, может даже каким-то образом сервисы. Но это не избавит от ошибок использования методов. При развитии программы могут появляться новые роли, менятся ответственность старых, и тогда придется отслеживать какой метод доступен для какой роли. В коде это должно превратиться в сущий ад и добавление новой роли или изменение ответственности будет не самой приятной задачей. К тому же вероятность ошибки все равно будет велика. Лучше определять роли доступа декларативно, таким образом будет легче управлять правами и сразу видно, что кому доступно. Легко вносить изменения и добавлять новые роли. Но обо всем по порядку.

Подробнее

PostSharp. Логирование

Продолжаем подробный разговор о аспекте OnMethodBoundary.  Данный аспект применяется, когда у вас есть доступ к исходным кодам метода и вы хотите отслеживать события начала вызова метода, конец вызова, исключение и успешность завершения.  Все это делается переопределением методов OnEntryOnExitOnException и OnSuccess соответственно.

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

Logging

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

Будем основываться на приложении из прошлой статьи. У нас готов интерфейс для отображения происходящего в системе. Так что можно начинать.

Подробнее

PostSharp. Генерация кода

Сегодня я хочу остановиться поподробнее на аспекте OnMethodBoundary.  Данный аспект применяется, когда у вас есть доступ к исходным кодам метода и вы хотите отслеживать события начала вызова метода, конец вызова, исключение и успешность завершения.  Все это делается переопределением методов OnEntryOnExitOnException и OnSuccess соответственно.

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

Code Generation

На мой взгляд, больше всего «бесполезного» кода появляется на пользовательских формах и представлениях (UserControl) для WinForms. Необходимо подписывать почти каждый элемент на событие щелчка, изменения состояния элемента. Это куча кода, которую можно не писать совсем в большинстве случаев, если принять некоторые соглашения и строить весь интерфейс на биндинге. В конечном итоге такая практика поможет лучше понять идеологию WPF, если вы еще не перешли на нее. Да и поддерживать и тестировать такое подход, на мой взгляд, легче.

Подробнее

PostSharp. Альтернативы

Я тут подумал, что несправедливо было бы обойти стороной сравнение PostSharp и других продуктов предоставляющих АОП. Ниже будут рассмотрены особенности использования, плюсы и минусы различных подходов. Но не думайте что PostSharp является серебрянной пулей. =)

Можно почитать и википедию насчет АОП и фреймворков для .Net платформы. Я посмотрел несколько перечисленных там фреймворков лично и по документированности и простоте использования остановился на PostSharp.

Containers (Инверсия зависимостей)

Большинство фреймворков направленных на инверсию зависимостей включают в себя некоторые возможности аспектно-ориентированного программирования. Для большинства достаточно простых технических требований, таких как трейсинг и обработка исключений применяемых к сервисам приложения, их возможностей хватает. Но их нельзя применить для более сложных и комплексных аспектов, которые могут применяться так же к объектам пользовательского интерфейса или к доменным объектам.

Продукты: Spring.NETCastle WindsorMicrosoft Unity

Плюсы:

  • Вы уже используете фреймворк для инверсии зависимостей
  • Аспекты могут быть настроены после сборки
  • Некоторые аспекты (трейсинг и обработка исключений) могут быть уже реализованы в вашем фреймворке.

Минусы:

  • Очень ограниченные возможности в плане АОП
  • Ваши объекты должны создаваться с помощью контейнера предоставляемого фреймворком. Такой способ нельзя применить для элементов пользовательского интерфейса, и во многих случаях для доменных объектов тоже.
  • Не работает со статическими, не публичными и/или не виртуальными методами. Так же не будет работать применение на поля, свойства и события классов.
  • Нет, или же плохое инструментирование для Visual Studio

Подробнее

PostSharp. Обзор. Часть I

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

Аспектно-Ориентированное программирование

Аспектно-ориентированное программирование (АОП) — парадигма программирования, основанная на идее разделения функциональности для улучшения разбиения программы на модули.

Существует достаточно много классов задач, решение которых невозможно в контексте ООП или же приведет к большой захламленности кода и связности модулей, что плохо. Например, логирование. Для того чтобы вести лог работы программы, необходимо в каждый метод поместить несколько служебных строчек вызова службы логирования, так же возможно придется ее передавать через входные параметры методов. Весь этот код не будет относиться к выполнению реальной задачи возложенной на метод, а только мозолить глаза. К тому же, сколько лишних строчек кода придется написать вручную!

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

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

Подробнее