Страницы с тегами : архитектура

Масштабирование ECM на SharePoint

Бытует мнение, что на для построения масштабируемого ECM решения на SharePoint  требуется глубокая кастомизация и без нее никуда. Причин этому много: широко известные Large List Threshold, тормознутые разрешения, Security Scopes Limit, довольно слабые возможности создания связей между элементами, ненадежный и невыразительный движок Workflow.

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

Принципы

Первая и самая важная ошибка, которую совершает большинство разработчиков – использование хранилища SharePoint, как реляционной СУБД. В РСУБД тип данных соответствует расположению (таблице). При переносе этого принципе в SharePoint все документы, независимо от стадии их жизненного цикла, помещают в одну библиотеку. При такой архитектуре решение валится от нагрузки еще до достижения каких-либо лимитов.

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

Первый принцип ECM в SharePoint, который обязательно нужно применять с самого начала – разделять оперативные и архивные документы. Обычно объем оперативных документов составляет не более 20% от общего объема и со временем этот показатель уменьшается. Если в РСУБД архивность - это не более чем атрибут, то в SharePoint надо явно задавать политики, по которым документы будут перемещаться в архив.

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

Второй принцип ECM в SharePoint – использовать возможности поиска для построения выборок “всех” документов. “Всех” специально взял в кавычки, так как обычно нужны не все документы, а некоторая выборка по критериям. Для базовой реализации хватает встроенных возможностей SharePoint, сложные вещи потребуют разработки веб-частей, которые будут строить сложные поисковые запросы.

Третий принцип ECM в SharePoint, самый сложный для применения – не пытаться создать универсальную модель сущностей и связей для всего ECM, а сконцентрироваться на автоматизации конкретных процессов. Люди с аналитическим складом ума всегда пытаются обобщить механизмы работы системы, чтобы уменьшить её когнитивную сложность. Это, в свою очередь, ведет к усложнению реализации из-за частных случаев и процессов выбивающихся из общей картины. Нужно понять, что пользователям не придется сталкиваться со всей системой разом, они будут работать с малой частью системы в один момент времени. Для начала нужно исключить из лексикона слова “любой” и “все”, всегда рассматривать конкретные процессы и типы документов.

Инфраструктура

Когда разобрались с принципами нужно правильно подготовить инфраструктуру к реализации системы. Если вы еще не перешли на SharePoint 2013, то самое время это сделать. Также вам понадобится Exchange для электронной почты.

Для работы вам обязательно понадобятся четыре службы:

  • Служба поиска
  • Служба управляемых метаданных
  • Служба профилей пользователей (должен быть настроен импорт из AD)
  • Служба управления приложениями (App Management Service)

Эти службы должны работать и быть правильно настроенными, чтобы все возможности были доступны.

Обязательно нужно поставить и подключить к SharePoint серверы Workflow Manager и Office Web Apps.

На ферме SharePoint обязательно надо настроить исходящую и входящую электронную почту, а также создание групп рассылки в AD, чтобы можно было отправлять почту группам

Далее вам понадобится как минимум три коллекции сайтов (не считая коллекции сайтов портала, MySiteHost и App Catalog):

  • ECM Control Center – коллекция сайтов с включенными фичами Content Type Syndication Hub и Document ID. Шаблон может быть любой. В службе управляемых метаданных необходимо вписать url этой коллекции в поле Content Type Hub (подробнее - http://www.wictorwilen.se/Post/Plan-your-SharePoint-2010-Content-Type-Hub-carefully.aspx)
  • Архив – коллекция сайтов из шаблона Центр Записей (Records Center). Архив желательно разместить в отдельной БД и настроить Remote Blob Storage.
  • Коллекция сайтов с оперативными документами. В зависимости от информационной архитектуры фермы может быть несколько таких коллекций. Рекомендую сразу включить и настроить фичу Document ID в этих коллекциях.

В настройках фермы создайте подключение для отправки документов (Send To Connection) и укажите в качестве назначения урл организатора контента в коллекции узлов архива (Подробности тут: http://office.microsoft.com/en-gb/office365-sharepoint-online-enterprise-help/configure-send-to-connections-for-records-management-HA102895194.aspx).

Кстати это все доступно и в Office 365, вам необходимо будет только создать коллекции сайтов архива и оперативных документов. Для content type hub автоматически создается коллекция узлов, не видимая в списке в панели администрирования.

Схема данных

Когда ферма готова надо начинать описывать типы контента документов. Все типы контента необходимо создавать в ECM Control Center. После создания типы контента необходимо опубликовать и механизмом синдикации эти типы будут копироваться в остальные коллекции сайтов вместе с полями, формами, шаблонами документов и политиками.

Надо учитывать, что lookup поля не поддерживаются при синдикации, поэтому все лукапы надо заменить на поля выбора, поля метаданных или ссылки на DocID (придется сделать custom renderer).

Рабочие процессы

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

Процессы  могут быть двух видов:

  • Структурированные – когда есть схема и четко прописаны роли.
  • Ad-hoc процессы – когда набор участников задается при запуске процесса, а маршрут заранее не определен или определен частично.

Для Ad-hoc процессов удобно использовать встроенные в SharePoint рабочие процессы утверждения и сбора отзывов. Важно следить чтобы ad-hoc процессы работали в рамках небольшой группы людей, иначе процессы будут очень сильно буксовать.

Структурированные процессы могут затрагивать людей из разных подразделений и выполняться довольно долго, а также содержать нетривиальную логику ветвления. Для таких процессов имеет смысл использовать workflow в режиме SharePoint 2013, созданные в SharePoint Designer и, возможно, допиленные в Visual Studio.

Для структурированных процессов необходимо создать группы SharePoint под каждую роль в процессе. Это сильно упростит вопросы замещения отсутствующих пользователей и делегирование обязанностей (достаточно будет добавить человека в группу).

Для каждого процесса необходимо создать свой список с нужным типом контента и цеплять рабочие процессы к этому списку. Для каждой группы процессов, сходных по целям, создавайте отдельный сайт. Например для согласования договоров отдельный сайт, с несколькими списками: договоры с подрядчиками, договоры с клиентами; для командировок свой сайт, и так далее. Landing page сайтов наполните инструкциями о том, как работать с процессами. Желательно запишите видео.

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

Важно везде использовать ссылку на Document ID, вместо url файла.

Архивирование

Так как большая часть списков и библиотек в оперативных коллекциях сайтов будут иметь плоскую структуру, то они быстро превратятся в помойку. Надо настроить автоматическое архивирование с помощью политик жизненного цикла (retention policy). Их можно цеплять как к типам контента, так и к библиотекам или папкам. Например можно назначить политику – перемещать в архив документы через месяц (неделю, год, на ваше усмотрение) с даты последнего изменения. (подробнее тут - http://www.c-sharpcorner.com/uploadfile/anavijai/retention-policy-for-a-document-library-in-sharepoint-2010/). Кроме того операцию перемещения в архив можно добавить в виде действия рабочего процесса.

В Архиве необходимо настроить Content Organizer, чтобы он размещал документы по папкам. Content Organizer умеет раскладывать документы по подпапкам в зависимости от атрибутов типа контента, а также умеет создавать подпапки при достижении границы количества элементов (чтобы исключить Large List Threshold).

Еще одна возможность, которой обязательно надо пользоваться – “объявление записью”. По сути это полная блокировка изменения документа. В архиве можно настроить автоматическое объявление записью всех попадающих в него документов.

Поисковые представления

В SharePoint 2013 колонки сайта автоматически превращаются в managed properties поиска. Но, увы, без атрибута refinable. Поэтому для начала вам надо будет создать в схеме поиска нужные managed properties. Также удобно создать типы результатов (Search Result Type) под каждый тип документа.

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

Заключение

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



Нелегкая судьба Best Practices

НеНаступи_small

(картинка отсюда)

Именно такое отношение к лучшим практикам встречается чуть менее, чем всегда. Можно подумать что не все знают про эти best practices. Но как только человек делает что-то не так, ему сразу же указывают как делать правильно. И что после этого происходит? НИЧЕГО. Только единицы начинают делать правильно после того как узнают про best practices, остальные продолжают жрать кактус и плакать о плохих менеджерах\вендорах\подрядчиках\клиентах\государстве.

Почему так происходит?

  1. Люди последовательны. Если человек уже что-то делает одним образом, то существует психологический барьер делать по-другому.
  2. Люди избегают потерь. Потому что в "другой путь" уже вложено много сил, и есть психологический барьер отказаться от этих "результатов" и пойти правильным путем.
  3. Люди не хотят быть неправыми. Есть у людей такой психологический механизм, который рационализирует любое нерациональное поведение. Даже если первоначальные действия были просто ошибкой, то человек придумает 100500 причин почему этот путь был самым правильным.

Вывод

Если кто-либо (в том числе Вы) не следуете best practices, то для этого почти никогда нет никаких рациональных причин. Когда следующий раз вы узнаете про лучшие практики в вашей области и подумаете "это мне не подойдет потому что...", остановитесь, и еще раз взгляните на картинку в начале поста.



Как сделать хороший корпоративный портал

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

Взгляд ИТшника

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

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

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

Взгляд дизайнера

По сравнению с ИТ специалистами это другая крайность. Порталы, придуманные дизайнерами, очень красивы. Скругленные углы, наклоненные шрифты, надкусанные фрукты. Такие картинки очень нравятся топам.

Но корпоративный портал – не сайт-визитка. Когда ИТшники пытаются впихнуть на портал функционал (все таки портал – ИТ актив), то дизайн портала начинает “плыть”. Контент, необходимый чтобы поддерживать красивость дизайна, оказывается создавать очень сложно и этим никто не занимается.

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

В “дизайнерском” техническом задании очень мало уделяется функционала описанию, зато много визуальным элементам и макетам страниц.

Взгляд архитектора

Здесь речь пойдет об Information Architect, но на адекватного перевода на русский я не нашел.

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

Архитекторы стремятся сделать портал удобным и понятным, но без помощи дизайнеров не могут сделать его привлекательным для пользователей, а без помощи ИТ – полезным.

Так как большинство Information Architect занимаются документооборотами, то даже портал в их представлении больше похож на файлопомойку. Очень структурированную, управляемую, с хорошей навигацией, поиском, механизмами compliance, но файлопомойку.

Взгляд бизнесмена

Сочетание всех трех предыдущих взглядов необходимо для создания хорошего корпоративного портала. Но не достаточно.

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

Естественно лояльность и продуктивность для всех сотрудников разом увеличить не получится. Для начала нужно четко определить цели, желательно по методике SMART. Для каждой цели должны быть метрики достижения, а также целевая аудитория пользователей, релевантная данной цели. Целевая аудитория (aka сегмент пользователей) далеко не всегда будет соответствовать организационным единицам или должностям.

Далее нужно определить последовательность действий, которая приводит к достижению целей (заполнить профиль, просмотреть видеоролик, итп). После этого нужно всячески завлекать пользователей на портал и следить за метриками достижения целей. Далее можно всячески улучшать показатели.

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

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

Заключение

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



Многоликий SharePoint

Я часто консультирую людей по поводу SharePoint, и каждый раз я слышу примерно одно и то же: “мы планируем\разрабатываем\внедряем\используем\хотим_выкинуть портал на SharePoint”. Такое ощущение, что единственное для чего предназначен SharePoint – делать порталы. Как битрикс или, не дай бог, друпал. Ситуацию еще подогревают HRы, которые хотят “интранеты” (имея ввиду ровно тоже, что и порталы).

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

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

Типовой корпоративный портал на SharePoint

Обычно на портал возлагаются следующие задачи:

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

Самое странное, что многие цели противоречат друг другу, но это никого не смущает. Например документооборот крайне плохо сочетается с уникальным дизайном. Никому в голову не придет делать уникальный дизайн в Documentum или DocsVision, а в SharePoint это нормально. Хранилище активов требует разграничения доступа в соответствии с организационной структурой, а совместная работа и улучшение коммуникаций, наоборот, требует преодоления рамок организационной структуры. Весь feature soup, который предлагается в качестве полезного функционала, вообще ни как не коррелирует с заявленными целями и присутствует, в основном, “для галочки”. И это еще не самое страшное…

Самое страшное начинается когда этот портал пытаются реально использовать. Ведь бизнес динамичен, постоянно требуется что-то поменять, подкрутить, дать доступ, создать сайт, изменить страницу. Но универсальное “портальное решение” больше напоминает не гибкую систему, а изваяние из гранита, которое даже передвинуть нельзя, не то что как-то поменять.

Приспособить “портал” под конкретные задачи пользователей оказывается сложно, а без этого adoption становится низкий и вложения не окупаются. Гигантский набор фич на портале используется от силы на 20% и, зачастую, страдает от проблем масштабирования.

Почему так происходит

Ситуация описанная выше повторяется чуть менее, чем всегда. Казалось бы зачем покупать порталы, когда они приводят к неудовлетворительному результату. Но проблема в том, что все продают “корпоративные порталы”. Все это не только Microsoft и партнеры, это в том числе те, кто внедряет другие технологии, от вики движков, до битриксов и WebSphere. Тут работает принцип социального доказательства: “если все остальные покупают корпоративные порталы, то чем мы хуже”.

Сам термин корпоративный портал является ментальным шорткатом, который избавляет продавца и покупателя от необходимости выяснения потребностей. Кроме того, для продавца продать "корпоративный портал” – это хороший способ продать проект допиливания портала под конкретные нужды.

Я думаю для многих не секрет, что некоторые вендоры “корпоративных порталов” по факту не имеют портала как продукта (распространяющегося без программистов).

Как сделать правильное решение

Для создания хорошего решения на SharePoint необходимо:

  1. Сосредоточиться на целях
  2. Поставить измеримые KPI
  3. Планировать информационную архитектуру
  4. Создавать самые простые решения

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

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

Примеры решений на SharePoint

Корпоративный поиск

Цель – уменьшить время на поиск информации.
KPI – количество успешных запросов (с кликом на результат) и количество неуспешных (без результатов или без клика на результат). На основании этих величин можно получить экономический эффект и вычислить целевые значения.
Архитектура – искать “везде” обычно плохо работает. Смотрите на поисковую выдачу интернет-поисковиков. Там есть разные типы информации, поиск по разным источникам, продвигаемые результаты,actionable результаты. Адаптируйте к своим источникам и внедряйте.
Решение – стандартный поиск SharePoint 2013. После внедрения поисковая аналитика и “тюнинг” поиска.

Рабочие области команд и проектов

Цель – увеличить эффективность совместной работы.
KPI – количество пересылаемых по электронной почте документов. Взять baseline до запуска системы, уменьшить на 30%-50%-80% по вкусу.
Архитектура – необходимо сделать максимально простой процедуру создания сайтов с библиотекой и списками для совместной работы. Без заявок в ИТ и согласований.
Решение – стандартные сайты команд SharePoint, плоские разрешения, контролируемый жизненный цикл. Обучение пользователей возможностям платформы.

Корпоративный сайт

Цель – сделать единую точку входа для информационных ресурсов компании.
KPI – Количество просмотренных страниц сайта (новостей, событий, фото\видео материалов), количество опубликованных, процент сотрудников, ответивших на опросы. Каждая новость, опубликованная на сайте, должна быть прочитана значительным количеством сотрудников (30% и более), при определенном темпе публикации можно получить довольно точные количественные характеристики.
Архитектура – фиксированные типы информации, малое количество редакторов, простая система разрешений. Участие пользователей – лайки и комментарии, ответы на опросы.
Решение – отдельная коллекция сайтов с режимом публикации, кастомный дизайн, фиксированная структура. Обязательное обучение авторов контента.

Документооборот

Цель – уменьшить время согласования.
KPI – Время согласования документов (по типам). Можно взять baseline с текущей ситуации, уменьшить на 30%-50%-80% по вкусу.
Архитектура – фиксированные маршруты, роли, типы документов. Это очень важный момент. Если в согласовании может принимать участие произвольное количество людей, то считать KPI становится невозможным. Если документы нельзя разделить по типам, то тоже вызывает проблемы расчета KPI.
Решение – Отдельный сайт или коллекция, типы контента, шаблоны, workflow. Предусмотреть вычисление количества дней\часов\минут на согласование. Ну и без обучения, скорее всего, никуда.

Специализированные варианты решений:

  • Enterprise Content Management \ Электронный Архив
  • Автоматизация заявок
  • Базы знаний
  • Системы оценки персонала
  • Системы внутренних вакансий

Попробуйте на досуге продумать конкретные цели и KPI таких систем.

Самое важное – все это разные системы. Нет смысла все валить в одну кучу и называть “корпоративным порталом”, так достичь KPI не получится.



Облачная vs on-premise экономика

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

Как планируются решения on-premise

Кстати on-premise переводится как “на предприятии”, что означает использование собственных ресурсов, вместо арендованных.

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

Для организаций, не имеющих мощного ДЦ, эта проблема еще более актуальна. Развертывание новых серверов может занимать от нескольких недель до нескольких месяцев.

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

Такой подход влияет как на сайзинг (планирование железа), так и на архитектуру решений, так и на лицензии программного обеспечения.

Почему в облаке это неправильно

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

Если вы в облаке заранее резервируете в 10 раз больше ресурсов, чем необходимо сейчас, то вы платите в 10 раз больше, хотя по факту большая часть ресурсов простаивает. Тоже самое касается лицензий на ПО. Нет смысла покупать 8 процессорных лицензий для SQL Server за несколько миллионов, если ваше решение сможет три месяца бегать на двух процессорах, а еще девять месяцев на четырех. Суммарные затраты на три года аренды лицензий и серверов в Azure будут ниже стоимости одних лицензий для on-premise.

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

Как работает облачная экономика

В облаке всегда начинайте с малого. Вам не нужно три воркера и распределенный кеш, вам не нужно 4 WFE для SharePoint, вам не нужна A7 виртуалка с SQL Server. Скорее всего вы можете обойтись в 2-3 раза меньшими ресурсами. Если вы в начале пути, создаете новое веб-приложение или разворачиваете ферму SharePoint – выделяйте минимум ресурсов.

Когда ваше решение начинает масштабироваться – следите за профилем нагрузки. Нет смысла все время держать кучу воркеров, если они ничего не делают. Отключайте виртуалки, если средняя загрузка ниже 50%, а всплески не поднимают её выше 75%. Добавляйте новые диски в виртуалку и SQL Server, так как именно в IO упирается производительность SQL, а платите вы все равно за место.

Когда ваше решение получит более-менее стабильный профиль нагрузки, тогда занимайтесь оптимизацией. Нет смысла оптимизировать облачное решение, когда вы платите за него 10,000 рублей в месяц. Даже если вы сэкономите 10%, то это будет незначительная сумма. Когда ваше решение будет стоить 100,000 в месяц – уже стоит задуматься об оптимизации.

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

Когда перестает работать облачная экономика

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

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

Заключение

Статья получилась в стиле Капитана “Очевидность”, но я каждый день сталкиваюсь с непониманием сути облачной экономики. Может кто-нибудь найдет эту статью, прочитает и начет думать по-другому.



Применимость DDD

До сих пор не утихают холивары на тему DDD\rich vs anemic. С одной стороны апологеты DDD (domain driven design, дизайн на основе предметной области) твердят о том как это круто, с другой стороны говоря что оно не везде подходит. На вопрос где же оно подходит обычно затрудняются ответить или отвечают “for compex domain”, причем примеров применения такого встретить непросто.

 

Попробуем разобраться. Если отбросить всю философскую шелуху DDD, то придем к очень простой концепции жирной (rich, насыщенной) модели, описанной Фаулером. С одной стороны Фаулер предлагает поместить логику в классы “сущностей”, соответствующие данным предметной области. С другой стороны он прекрасно понимает что логика будет сложна и надо каким-то образом декомпозировать её. Кроме того есть логика, которая оперирует более чем одной сущностью и поместить её в один из классов сущностей не выгодно. Таким образом создаются классы сервисов, стратегий итп. Их всех объединяет свойство, что они не содержат данные предметной области и для работы обращаются к классам сущностей. По сути вся сложная логика располагается в этих самых сервисах.

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

Тут стоит отступить назад и посмотреть на общую картину. Как выглядит код приложения, использующий жирную модель (на основе модели в статье Фаулера):

class ContractsController
{
    public Result CalculateRecognitionsAction(int contractId)
    {
        var contract = repository.GetById(contractId);
        contract.CalculateRecognitions();
        repository.Save();
    }
}


SOLID

Эта аббревиатура является самой известной (после ООП), она говорит нам о 5 принципах “хорошего дизайна ПО”. При этом является самой бесполезной, потому что однозначно никто не может обозначить критерий для того или иного принципа. Часто на форумах приходится видеть споры о том у кого программа SOLIDнее.

Про SOLID пишут часто и много, но большинство пишущих не читали или мало читали первоисточник (признайтесь, вы читали?). Автор аббревиатуры SOLID - Роберт Мартин, он придумал саму аббревиатуру и описал 5 принципов. На самом деле он описал больше, но звучных буквосочетаний не придумал, многие вещи остались забытыми. Заметьте что Мартин именно описал принципы, он не является их автором. Зачастую объяснения на пальцах на примерах сложно перенести в свой код.



Who is mister SOLID?

Аббревиатура (длинное и неприятное слово) SOLID состоит из:

  • Single Responsibility Principle (SRP) – принцип единственной отвественности
  • Open\Close Principle (OCP) – принцип открытости\закрытости
  • Liskov Substitution Principle (LSP) – принцип подстановки Лисков (это фамилия)
  • Interface Segregation Principle (ISP) – принцип изоляции интерфейсов
  • Dependency Inversion Principle (DIP) – принцип инверсии зависимостей

Далее буду пользоваться только акронимами, указанными в скобках.

Критика

Как связаны между собой вышеуказанные принципы никто не говорит, какой из них важнее, а какой нет – тоже никто не в курсе.

Разберем по отдельности все 5 принципов, для описания буду брать из википедии. Вероятнее всего именно это описание найдет человек.

SRP

На каждый объект должна быть возложена одна единственная обязанность.

Первое же определение взрывает мозг. Что такое обязанность? Мартин определяет обязанность как причину изменения. Стало понятнее? Мне не очень.

OCP

Программные сущности должны быть открыты для расширения, но закрыты для изменения.

Это как вообще? Открыты для расширения – еще куда ни шло, а что значит закрыты для изменения? Скомпилированный код и так поменять нельзя, а если правятся исходники, то какая разница?

LSP

Объекты в программе могут быть заменены их наследниками без изменения свойств программы.

Тут немного лучше, потому что принцип LSP предельно формален, про него подробнее напишу ниже.

ISP

Много специализированных интерфейсов лучше, чем один универсальный.

Это Мартин  решил поиграть в Капитана Очевидность.

DIP

Зависимости внутри системы строятся на основе абстракций. Модули верхнего уровня не зависят от модулей нижнего уровня. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Это просто бред, написанный для красного словца. Если все зависит от абстракций, то как понять где модули верхнего уровня, а где нижнего?

У Мартина, кстати, не такое определение.

Терминология

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

Итак определения

Интерфейс – некоторый набор функций (их параметров и возвращаемых значений), с помощью которого одна часть программы обращается к другой.

Контракт – надмножество интерфейса, описывающее также поведение функций, ограничения на входные\выходные параметры, инварианты, последовательность вызовов итд. Контракт обычно присутствует в программе неявно, но есть средства, позволяющие часть его описать явно. Например навороченные системы типов как в haskell, внешние средства вроде Code Contracts в .NET. Даже если контракт не определен явно, то в программе он неявно присутствует.

Абстрактный интерфейс – некоторый тип данных,состоящий из набора методов без реализации. Всегда соответствует некоторому интерфейсу.

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

Модуль – некоторое множество функций и, возможно, данных, объединенные для решения задачи. Модулем могут быть как классы в ОО-языках, так и другие средства группирования кода. Модуль также имеет интерфейс и контракт, скорее всего один.

Принципы

Для начала стоит сказать что многие принципы не являются прерогативой ООП, а применимы для широкого класса парадигм.

Начнем с SRP

Если часть некоторого модуля не имеет никаких ссылок на другую часть этого модуля, то эти части можно разделить на разные модули. Если модули могут меняться независимо, то разделить нужно.

Начинать стоит с простого: если можно отделить – надо отделить. Необходимо чтобы внутри одного модуля весь функционал был связан между собой (high cohesion, такое словосочетание вы наверное слышали). Принцип работает только в одну сторону: если подмножество A некоторого модуля не имеет ссылок на подмножество B, то это не значит что B не имеет ссылок на A, причем скорее всего именно B будет ссылаться на A.

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

Модули будут зависеть друг от друга, они будут выстраиваться в ориентированный граф. Расположив зависимости сверху вниз можно условно разделить модули на верхне- и нижне- уровневые. На самом “пространство”, в котором мы пытаемся упорядочить модули, многомерно. Придумать одно отношение порядка для всего этого пространства невозможно. Но для двух модулей, между которыми есть путь, можно сказать какой из них верхнеуровневый, а какой нижнеуровневый.

Зависимость между модулями может быть:

  1. Ссылочной, когда модуль A непосредственно обращается к модулю B, его функциям и данным.
  2. Наследованием, когда модуль A является частным случаем B.
  3. Зависимостью по состоянию, когда два модуля оперируют одним внешним состоянием (глобальные переменные, файлы, БД) и влияют на работу друг друга. Это плохая зависимость, от нее надо избавляться.
  4. Зависимостью по времени. Когда для работы требуется одного модуля требуется вызов функций другого модуля в нужные моменты. Это самый плохой вид зависимости, он него надо избавляться однозначно всеми возможными способами.
 
Далее ISP

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

 

Перейдем к DIP

Этот принцип говорит нам что для двух ссылочно связанных модулей надо создавать абстрактный интерфейс. Оформлять модуль, от которого зависят другие модули, в виде класса, реализующего данный абстрактный интерфейс. Зависимый модуль должен обращаться к абстрактному интерфейсу, а не к конкретному классу. (low coupling, тоже слышали)

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

 

Теперь рассмотрим LSP

Принцип подстановки Барбары Лисков сформулирован предельно формально и говорит вообще о любых типа, а не только классах ООП.

Если A является подтипом B, то в любом месте программы (функции), где требуется объект типа B, можно подставить объект типа A и поведение программы (функции) при этом не изменится.

В ООП если класс A унаследован от класса B, равно как класс A реализует абстрактный интерфейс B, то A является подтипом B, а B является супертипом A.  Кроме того некоторые языки программирования поддерживают вариантность типов, для них тоже надо применять LSP, но там помогает компилятор.

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

Для контрактов правила простые:

  1. Предусловия в подтипе должны быть не сильнее, чем в супертипе.
  2. Постусловия в подтипе должны быть не слабее, чем в супертипе.
  3. Перечень выбрасываемых исключений в подтипе должен быть не шире, чем в супертипе. (хотя часто на это не обращают внимания)
  4. Остальные детали контракта, которые нельзя проверить статически, должны проверяться тестами, и подтипы должны проходить все тесты, которые проходят супертипы.

 

Напоследок OCP

Хорошо понимая LSP легко сообразить о чем говорит OCP.

Все не-sealed классы должны быть спроектированы таким образом, чтобы наследники не могли нарушить LSP.

Ну вот и все.

Что не вошло в пятерку

Принцип бритвы Оккма

Не плодите сущности без нужды

После активного применения SRP у вас будет много маленьких модулей, вплоть до одиночных функций. Тривиальные функции можно непосредственно инлайнить в вызывающий код, простые функции также можно перенести, если они используются только в одном месте. Отдельные функции можно объединять в модули по смысловому назначению, а также по параметрам, задавая их на уровне модуля, а не отдельных функций.

Do not repeat yourself (DRY)

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

Command-Query Separation (CQS)

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

Пожалуйста не путайте этот принцип с модным нынче CQRS, который является гипертрофированным CQS для непонятно каких целей.

Keep it simple, stupid! (KISS)

Делайте все настолько простыми, насколько можно, но не проще.

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

Заключение

Самыми важными принципами в начале проектирования частей программы являются KISS и SRP. После того как появился некоторый граф модулей надо сразу применять Бритву Оккама, LSP, ISP. Когда начинаете писать код, то применяйте DRY, DIP, CQS и OCP.

Ну вот теперь совсем все.



Архитектура и дизайн ПО

На тему обсуждения на RSDN.

Целью данного поста является разделение понятия архитектуры и дизайна ПО. Постоянно возникают непонимания чем же эти два понятия отличаются. Одному зачастую приписываются свойства другого.

Итак.

Архитектура ПО — некоторые рамки в пределах которых будет строиться ПО. Например будет ли приложение веб или декстоп, будет ли оно размещено в "облаке" или нет. Будет ли использовать реляционную СУБД или какую-то другую. С какими другими программами придется взаимодействовать и как это делать. Используемые языки и технологии.
Архитектура мало коррелирует с конкретными задачами.
Архитектура определяет подход к решению некоторого класса задач, и наоборот, некоторый класс задач может быть решен определенными архитектурными приемами.


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

Архитектура определяет дизайн. Используемые языки и технологии сильно влияют на используемые паттерны.

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

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

Еще раз вкратце. дизайн решает задачи, архитектура создает “окружение” для решения задач.



Плачь по SOA

Наверное все слышали о SOA, но у большинства эти три буквы ассоциируются исключительно с ws-* вебсервисами. Хотя на самом деле это очень хорошая концепция построения программной системы из компонент, абсолютно не привязанная к способам реализации взаимодействия.

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

Так как сервисы не обладают идентичностью, а все ссылки на сервисы с одним контрактом равнозначны, то это позволяет динамически изменять систему, подменять один компоненты другими и достаточно просто балансировать нагрузку.

В мире ws-* вебсервисов контракты реализуются с помощью WSDL, а общеизвестными сервисами являются брокеры, которые по WSDL могут возвращать ссылки на сервисы. Сейчас наблюдается практически полное отсутствие ws-брокеров на просторах интернета. WSDL не описывает семантику, а только синтаксис, поэтому просто получить ссылку на сервис не получится, неизвестно вообще говоря что этот сервис делает. Кроме того нету стандартных контрактов, каждый вендор делает такой контракт как захочется. Это все приводит к тому что идея брокеров на практике оказывается нежизнеспособной. В большинстве библиотек вебсервисов не реализована поддержка UDDI – протокола общения с брокерами. Глобального коммунизма не будет.

А вот в отдельно взятой стране программе такой коммунизм построить можно. Роль контрактов будут играть интерфейсы языка, роль сервисов – объекты, реализующие интерфейсы, а в качестве брокера будет выступать IoC-контейнер. Он как раз умеет по интерфейсу отдавать ссылку на сервис, а его возможность собирать зависимости позволит избавить сами сервисы от общения с брокером.

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



Ортогональность

Навеяно холиварами на RSDN…

Если вы читали книгу «Программист-прагматик» Эндрю Ханта и Дэйва Томаса, то наверное знаете о чем пойдет речь.

Ортогональность также называют Separation of Concerns или применением принципа “Разделяй и властвуй” в архитектуре программ, принцип SRP является отражением идеи ортогональности.

Сам термин заимствован из геометрии и обозначает что линии пересекаются под прямым углом (на самом деле из алгебры и обозначает что скалярное произведение векторов равно нулю). В программировании этим термином обозначают независимость.

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

Вы сами часто сталкивались с ортогональностью в разных проявлениях:  разделение модели и представления, отделение Data Access Layer от Business Logic Layer, разделение данных и алгоритмов их обработки в паттернах State, Strategy.

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

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

Использование IoC-контейнеров делает управление зависимостями и временем жизни объектов независимым от пользователей этих объектов. AOP ортогонализирует (ух какое слово) так называемую сквозную функциональность. Методу, результат которого кешируется, и вызывающему его коду абсолютно не надо знать что происходит кеширование и как оно происходит. Применение паттернов MVC, MVP, MVVM делает независимыми сам интерфейс, от логики работы с низлежащей моделью, и даже если модель переедет на другую машину в сети, то интерфейс править не придется. Это все примеры ортогональности.

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

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

Информация от алгоритмов её обработки не зависит поэтому они должны быть отделены. Это не значит что объекты с методами должны быть без полей. Во-первых многие объекты могут быть параметризованы, во-вторых некоторые объекты могут иметь внутреннее изменяемое состояние, то таких объектов обычно очень мало.

Под конец лирического отступления хочу привести пример очень популярного способа нарушать ортогональность.

Доменная модель или почему Фаулер неправ.

Domain Model – очень популярный паттерн построения бизнес-логики в бизнес-приложении. Заключается как раз в объединении данных, хранимых чаще всего в БД, и методов бизнес-логики в одном объекте. Все это преподносится как соответствие модели предметной области из реального мира.

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

Во-первых не все методы бизнес-логики удается распихать по доменным объектам, приходится создавать искусственные объекты – контейнеры методов, что уменьшает согласованность и ухудшает читаемость.

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

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

Заключение

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