четверг, 3 апреля 2014 г.

Office 365 Day

17 апреля 2014 года состоится мини-конференция Office 365 Day в Microsoft Technology Center на Белорусской.

Раньше встречи были посвящены в основном SharePoint, теперь расширяем формат. Office 365 это не только SharePoint, но и Lync, Exchange, Yammer, Office, Project, Dynamics CRM, облачные технологии и гибридные архитектуры.

В программе два потока: технологический и бизнес-ориентированный.
Предварительный перечень докладов:

  • Создание веб-сайта на базе Sharepoint Online - Виталий Жуков
  • Создание корпоративного портала в Office 365 – Сергей Слукин
  • Стратегия миграции внутренних решений в Office 356 – Александр Романов
  • Новые API и возможности приложений Office – Михаил Бондаревский
  • Облачный инструмент совместной работы – Yammer. Кто здесь? – Роман Марусяк
  • Гибридные среды. Выгоды и проблемы – Станислав Выщепан

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

Регистрация на мероприятие обязательна, регистрироваться по ссылке -http://o365day.timepad.ru/event/116000/

До встречи.

 

понедельник, 10 февраля 2014 г.

Онлайн курсы и материалы для изучения SharePoint

Про изучение SharePoint 2010 для разработчиков и администраторов я писал два с половиной года назад, почти все материалы до сих пор доступны:

В SharePoint 2013 появилось много новых возможностей. Теперь для разработчика недостаточно просто уметь писать веб-части и event receivers. В SharePoint 2013 поставить ферму для разработки – само по себе требует многих навыков, а разработчику надо еще как минимум уметь настраивать поиск, управляемые метаданные, профили пользователей, apps и workflow.

Чистая разработка для SharePoint 2013 идет в сторону apps (ASP.NET), но закрывает лишь малую часть потребностей заказчиков. Навыки развертывания, администрирования и использования стандартного функционала оказываются для разработчиков чуть ли не важнее навыков писать код.

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

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

  1.  http://technet.microsoft.com/en-US/sharepoint/fp123606 - SharePoint 2013 training for IT pros.
  2. http://msdn.microsoft.com/en-US/office/dn448488 - Office 2013 developer training videos. Пусть не пугает называние, большая часть курса – по SharePoint 2013.
  3. http://www.microsoft.com/resources/Technet/en-us/Office/media/ITProPivotViewer/ – интерактивный браузер всего контента Technet.
  4. http://technet.microsoft.com/en-US/projectserver/jj906608 - Project 2013 training for IT pros and developers.
  5. https://channel9.msdn.com/Events/SharePoint-Conference/2012 – видео с конференции SharePoint Conference 2012, в докладах часто можно встретить темы, отсутствующие в документации.
  6. http://pluralsight.com/training/Courses#sharepoint – Pluralsight, крайне рекомендую. За $300 в год (меньше цены одного курса в УЦ) вы получите 99 (на сегодня) и более (в будущем) курсов по SharePoint 2007-2013. Некоторые из них содержат уникальный контент, который более нигде не доступен.
  7. http://www.microsoftvirtualacademy.com/Studies/SearchResult.aspx?q=SharePoint – курсы на Microsoft Virtual Academy, есть очень полезные курсы с глубоким погружением в тему.
  8. http://code.msdn.microsoft.com/officeapps/Apps-for-SharePoint-sample-64c80184 - Примеры приложений для SharePoint, увы, код не всегда рабочий.
  9. http://social.technet.microsoft.com/wiki/contents/articles/14579.sharepoint-2013-books-a-comprehensive-list.aspx – список книг по SharePoint 2013, но если вы изучите все по ссылкам выше, то вам надо будет только прочитать Inside SharePoint 2013.
  10. http://spf2013faq.mindsharp.com/Lists/SharePoint%202013%20Books%20and%20Extracts/V%20Books.aspx – тоже список книг.

Для начала хватит. Как обычно нужно много и внимательно читать MSDN и TechNet.

Изучайте, пользуйтесь, создавайте хорошие решения.

среда, 5 февраля 2014 г.

Поиск в приложениях SharePoint. Часть 3.

В SharePoint 2013 появился REST веб-сервис, который позволяет делать поисковые запросы из JavaScript. В SharePoint 2010 есть только search.asmx, который требует генерировать и парсить большой объём XML (в лучших традициях SharePoint).

Чтобы упростить жизнь разработчику клиентских компонентов я написал REST веб-сервис для SharePoint 2010.

Реализация

За основу взял метод, который описывал ранее - Javascript-enabled SharePoint WCF services.

Контракт у сервиса очень простой:

[ServiceContract]
public interface ISearch
{
    [OperationContract]
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    Stream Query(string q, int top, int skip, string select, string orderBy, bool includeRefiners, string refiners);
}

Параметры вызова:

  • q – текст запроса (обязательно).
  • top – количество результатов.
  • skip – с какой позиции в выборке отдавать результаты.
  • select – через запятую названия managed properties в результатах.
  • orderBy – через запятую названия managed properties по которым сортировать результат, после имени можно указать desc для сортировки по убыванию.
  • includeRefinerstrue или false, возвращать результаты уточнений или нет.
  • refiners - через запятую названия managed properties для формирования уточнений.

Реализация:

public System.IO.Stream Query(string q, int top, int skip, string select, string orderBy,
                    bool includeRefiners, string r) 
{
    using (new SPMonitoredScope("Execute Query Method"))
    {
        var site = SPContext.Current.Site;
        var result = GetSearchResults(site, q, top, skip, select, orderBy, includeRefiners, r);
        return ToJson(result);
    }
}

Метод GetSearchResults довольно простой, он передает параметры запроса в объект KeywordQuery и получает результат.

private static ResultTableCollection GetSearchResults(SPSite site, string q, int top, int skip, string select, string orderBy, bool includeRefiners, string r)
{
    var query = new KeywordQuery(site);
    query.QueryText = q;
    query.StartRow = skip;
    if (top > 0)
    {
        query.RowLimit = top;
    }

    FillSelectProperties(select, query);

    FillSortList(orderBy, query);

    query.ResultTypes = ResultType.RelevantResults;
    if (includeRefiners)
    {
        query.ResultTypes |= ResultType.RefinementResults;
        query.Refiners = r;
    }
    return query.Execute();
}

Методы FillSelectProperties и FillSortList парсят значения из строки запроса и заполняют свойства объекта KeywordQuery.

private static void FillSortList(string orderBy, KeywordQuery query)
{
    if (!string.IsNullOrEmpty(orderBy))
    {
        var orderByParts = orderBy.Split(new[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
        query.SortList.Clear();
        foreach (var part in orderByParts)
        {
            var pair = part.Split(' ');
            if (pair.Length > 1 && string.Compare(pair[1], "desc", System.StringComparison.OrdinalIgnoreCase) == 0)
            {
                query.SortList.Add(pair[0], SortDirection.Descending);
            }
            else
            {
                query.SortList.Add(pair[0], SortDirection.Ascending);
            }
        }
    }
}

private static void FillSelectProperties(string select, KeywordQuery query)
{
    if (!string.IsNullOrEmpty(select))
    {
        var properties = select.Split(new[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
        query.SelectProperties.Clear();
        query.SelectProperties.AddRange(properties);
    }
}

Теперь самая интересная часть – преобразование результатов в JSON. Для сериализации не подойдет стандартный DataContractJsonSerializer, он не умеет сериализовывать DataSet и DataTable в компактном виде. Со времен появления ASP.NET Ajax в библиотеке появился класс JavaScriptSerializer. Он не очень быстр, зато его легко расширять, чтобы получать ровно ту разметку, которая нужна и не требуется дополнительных библиотек.

Метод ToJson:

private static Stream ToJson(ResultTableCollection value)
{
    JavaScriptSerializer ser = new JavaScriptSerializer();

    List<JavaScriptConverter> converters = new List<JavaScriptConverter>();

    converters.Add(new DataRowConverter());
    converters.Add(new ResultTableCollectionConverter());
    ser.RegisterConverters(converters);

    var resultStream = new MemoryStream();
    var writer = new StreamWriter(resultStream);
    writer.Write(ser.Serialize(value));

    writer.Flush();
    resultStream.Position = 0;

    return resultStream;
}

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

ResultTableCollectionConverter:
internal class ResultTableCollectionConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(ResultTableCollection) }; }
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type,
                                       JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        var resultTableCollection = obj as ResultTableCollection;
        Dictionary<string, object> propValues = new Dictionary<string, object>();

        if (resultTableCollection != null)
        {
            if (resultTableCollection.Exists(ResultType.RelevantResults))
            {
                var resultTable = resultTableCollection[ResultType.RelevantResults];
                propValues.Add("TotalResults", resultTable.TotalRows);
                propValues.Add("Results", resultTable.Table.Rows.OfType<DataRow>());
            }
            if (resultTableCollection.Exists(ResultType.RefinementResults))
            {
                var refinersTable = resultTableCollection[ResultType.RefinementResults];
                propValues.Add("TotalRefiners", refinersTable.TotalRows);
                propValues.Add("Refiners", refinersTable.Table.Rows.OfType<DataRow>());
            }
        }

        return propValues;
    }
}

DataRowConverter:

internal class DataRowConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(DataRow) }; }
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type,
                                       JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        DataRow dataRow = obj as DataRow;

        return dataRow != null
               ? dataRow.Table.Columns.OfType<DataColumn>().ToDictionary(c => c.ColumnName, c => dataRow[c])
               : new Dictionary<string, object>();
    }
}

 

Применение

Возможность делать поисковые запросы на клиенте позволяет создавать чисто клиентские веб-части, которые не требуют для работы серверного кода. Для реализации этой идеи я реализовал одну базовую веб-часть, которая работает на jQuery и jsRender, и позволяет задавать параметры и настройки на уровне .webpart файла. Таким образом одни раз установив Farm Solution с веб-сервисом и базовой веб-частью появляется возможность добавлять веб-части с клиентским кодам в виде Sandbox решений.

Пример такого решения я, как обычно, выложил на codeplex:

Исходники - https://spsamples.codeplex.com/SourceControl/latest#SearchWidgetWebParts/

Релиз - https://spsamples.codeplex.com/releases/view/118068

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

Заключение

Это последняя часть серии про использование поиска в SharePoint 2010. Часть 1 и Часть 2 по ссылкам.

вторник, 4 февраля 2014 г.

Масштабирование 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.

понедельник, 3 февраля 2014 г.

Как поставщики решений SharePoint обманывают заказчиков

На днях получит вот такой коммент в обсуждении на Хабрахабре:

Государственный университет в регионе N хочет себе СЭД, пользователей на 100. Кроме СЭД хочет простенький портал, телефонную книгу, новости, календарики.
На Sharepoint Server денег тратить не хочется, да и нет необходимости — рейтинги, социальные сети, политики хранения контента не в почете у сотрудников.
Поэтому решили купить СЭД на Foundation, заплатив только за СЭД-надстройку (будем считать что лицензионные права на Foundation у них уже есть).


За 2-3 года документов скопилось около 60-80 тыс. (по всем группам). По ним нужно, в самом простейшем случае:
а) осуществлять быстрый и легко настраиваемый поиск (по конкретным атрибутам и без управляемых метаданных) по любым элементам и с учетом прав
б) быстро искать и исполнять задачи. задач при этом становится = (кол-во документов * 5)

Если знаете способ реализовать это на Foundation «изкаропки», пожалуйста, расскажите, очень интересно.

Исходный пост и обсуждение можете почитать по ссылке: http://habrahabr.ru/post/210844/#comment_7260770

Используя SharePoint Server, даже версии Standard, можно настроить быстрый и удобный поиск по документам и задачам. Это даже не потребует программирования, достаточно будет за день-два выполнить настройку поисковых представлений.

Решение, предлагаемое автором коммента, требует создания баз данных, custom service applications, собственного интерфейса пользователя и кода для привязки к стандартному функционалу. При очень хорошем раскладе такая разработка займет около двух недель.

Кажется, что решение на Foundation действительно выгоднее. Но на самом деле это обман.

Считаем стоимость

Так как решение делается для Государственного Университета, то стоимость лицензий на продукты Microsoft будет примерно в 10 раз ниже среднерыночной.

Я зашел на сайт http://www.msbuy.ru/ (не реклама, просто первый удобный калькулятор из выдачи гугла) и посчитал полный объем лицензий:

  • SharePoint Server – 1 шт
  • SharePoint Server Standard CAL  – 100 шт (на пользователя)
  • SQL Server Standard Core – 2 шт (4 ядра) 

У меня получилось 797 182.84 рублей. Лицензии на Windows Server не считал, так как они также нужны для Foundation. Для госуниверситета цена выйдет около 80 000 рублей. SharePoint Foundation, работающий на SQL Express, обойдется фактически бесплатно.

Даже если взять самых дешевых специалистов SharePoint, то их стоимость для заказчика составит не менее $60\час. Для SharePoint Server понадобится 16 часов работ по настройке представлений, для Foundation объем работ вырастет до 80 часов.

В деньгах:

  • Server – 16 часов =  $960 = 33 600 рублей.
  • Foundation – 80 часов = $4 800 = 168 000 рублей.

Внезапно решение на Foundation оказалось дороже, чем на Server, даже с учетом цены лицензий последнего.

Но и это еще не все.

Совокупная стоимость владения

Нужно понимать, что расчет выше касается одного аспекта функционала. Зачастую в решениях на Foundation создается много кода, имитирующего стандартный функционал платной версии SharePoint - поиск, профили пользователей (для хранения данных о пользователе), управляемые метаданные (структурированные справочники) и жизненный цикл документов. Например в SharePoint Standard справочник сотрудников (aka телефонная книга) и новости на портале можно сделать за два часа прямо в браузере. Подобное решение на Foundationобойдется в пару тысяч долларов минимум. В совокупности решение на Foundation, начинает стоить на порядок больше, чем решение на платной версии.

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

Обязательно стоит учитывать скрытую стоимость решений. Подробнее тут - http://gandjustas.blogspot.ru/2013/07/sharepoint.html.

С другой стороны платная версия SharePoint содержит много функционала, который можно использовать без кастомизации: поиск по внешним системам, мощные рабочие процессы согласования, совместное редактирование документов, личные узлы и удобный шаринг.  Даже если не рассматривать скидку на лицензии в 90%, как для Государственных Учебных заведений, то амортизированная стоимость лицензий на одно решение оказывается гораздо ниже. Кроме того, есть программы лицензирования, по которым цена лицензий оказывается значительно ниже.

Как продают впаривают

Тоже процитирую комментарий из обсуждения:

СЭД — это не портал. Принципы разграничения прав не по элементам, а по карточкам документов, например. То же самое и при отображении. Документ в СЭД — это же не просто элемент в списке или библиотеке, это элемент, связанный с кучей всего, вроде связанных файлов, других документов, журналов, поручений (которые еще связаны с задачами). Принципы работы довольно сильно отличаются. XXX for Sharepoint нужны как раз для адаптации Sharepoint к российскому документообороту, чего из коробки никак не сделать.

Мне, как техническому специалисту, это кажется смешным. В SharePoint Standard есть наборы документов, которые позволяют связывать несколько документов в одно целое, для связанных журналов и поручений нужно делать отдельные папки в списках, чтобы можно было давать доступ сразу на группу элементов. Всю автоматизацию моно сделать в workflow или с помощью небольших кусков кода. Это абсолютно не требует баз данных, custom service application и подобных “тяжелых” кастомизаций.

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

Заключение

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

Я понимаю, что есть и хорошие решения на Foundation, которые действительно делают что-то, что не умеет SharePoint Standard или Enterprise. Но таких решений очень мало, особенно на Российском рынке. А также вам надо удостовериться, что они идеально вам подходят, ибо доработка будет дорогая.

четверг, 30 января 2014 г.

Успех проекта SharePoint, где он?

Есть статистика, которая говорит, что более половины SharePoint проектов неуспешны (смотреть тут). С точки зрения бизнеса успешных проектов еще меньше, так как затраты оказываются выше, чем экономический эффект.

Проблема

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

Негативным эффектом такого способа ведения проектов становится то, что создается много кастомного кода. Ведь нельзя делать разработку, когда нечего положить в систему контроля версий. Обучая разработчиков out-of-the-box функционал, я много раз слышал вопрос о том, что же будет в итоге лежать TFS.

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

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

Как добиться успеха

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

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

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

Например, вместо огромного проекта “создания корпоративного портала” на полтора года и тысячи человеко-часов, можно запустить с десяток мелких проектов, каждый со своими KPI. Буквально через месяц по каждому проекту станет ясно имеет ли смысл его продолжать.

Может казаться, что это очень сильно увеличит нагрузка на менеджера. Если вам приходилось управлять двумя-тремя проектами сразу, то десять проектов может показаться адом. Но оказывается есть зубры, которые могут управлять и 50 проектами - http://www.linkedin.com/groups/How-many-projects-can-project-37888.S.210671311. Сказывается эффект масштаба – чем больше проектов, тем проще управлять каждым в отдельности.

Последнее, но самое важное тем не менее - минимизируйте объем кастом кода, особенно при работе с server-side object model. Чем больше кода, тем дороже поддержка, тем меньше шанс на успех.

Заключение

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

среда, 29 января 2014 г.

Простой способ повысить качество решений

image
Наверное каждый из вас сталкивался с такими решениями для SharePoint: решение вроде работает, но постоянно возникают какие-то проблемы, данные не сохраняются, странные падения при, казалось бы, безобидных операциях. Тестеры тратят много времени на такое решение, но исправление одних багов порождает другие. Развернуть такое решение на production ферме оказывается очень сложно, поддержка превращается в ад. Знакомо, да?

Занимаясь разработкой правил анализа кода для SPCAF (http://spcaf.com), я нашел способ как быстро исправить такую ситуацию.

Найдите все блоки кода такого вида:
try
{
    //код
}
catch(Exception e)
{
    //здесь что угодно, кроме throw;
}

Впишите throw; в блок catch. Важно что в catch указывается базовый Exception, а не конкретный тип исключения.
Ваше приложение начнет падать и вам надо будет исправить все найденные ошибки, не убирая throw. Я такое уже проделывал много раз на разных проектах, и это давало очень положительных результат. Даже если программисты будут сопротивляться, не допускайте убирания throw.

Исследование


Для тестирования правил я собрал около 70 .wsp файлов, решений SharePoint. Большинство из них — проекты, в которых мне довелось участвовать, и я прекрасно знаю все проблемы, которые возникали при разработке. Я посчитал плотность блоков try\catch без throw и вот что получилось:
  • Самое проблемное решение — 1 блок на 36 строк. То есть почти каждый значимый метод был завернут в такойtry\catch.
  • Решения средней паршивости — 1 блок на 90-100 строк. В некоторых из этих решений уже были проведены чисткиtry\catch.
  • Хорошие решения — 1 блок на 120-130 строк. С ними никогда не возникало проблем.

Обоснование


Перехват всех исключений не рекомендуется практически всегда, на него ругается Visual Studio Code Analysis, об этом написано в Framework Design Guidelines. В книге Pragamtic Programmer, которую стоит прочитать всем без исключения программистам, коротко и емко сформулировано правило — Crash, don't Trash.
Фактически перехват всех исключений это попытка подавить ошибку, допущенную программистом. Ошибка все равно вылезает, но не так очевидно и, зачастую, в совершенно другом месте. Это и создает проблемы при разработке решений. Особенно сильно это проявляется для SharePoint, так как его API крайне сложен.
Я знаю только один случай в решениях SharePoint когда оправдано ловить все исключения и не выбрасывать их дальше — в визуальных компонентах, чтобы ошибка разработчика не завалила портал. Но даже в них стоит рассмотреть обработку конкретных типов исключений, вместо перехвата всех подряд. В остальных случаях код должен падать максимально быстро и громко, желательно сообщая о том, что пошло не так. Не надо делать никаких возвратов false или null в случае исключения, пусть код упадет, тогда разработчики и тестеры увидят ошибку, до того как её увидит пользователь.

 

Заключение


Проблема подавления ошибок актуальна не только для SharePoint решений и не только на языке C# и платформе .NET. Возможно и в других проектах вы сможете значительно улучшить ситуацию убирая подавление исключений.
PS. Набор правил, которым проверял решения — http://spcafcontrib.codeplex.com/