SharePoint Script On Demand

В SharePoint 2013 довольно богатая клиентская библиотека. Ранее я уже писал об аналоге jQuery и об Ajax библиотеках. Одна из важнейших частей для разработки масштабного JavaScipt приложения – загрузчик скриптов. Такое тоже есть в SharePoint.

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

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

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

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

В мире веб-разработки фактически стандарт для управляемой загрузки скриптов – библиотека requirejs. Но в ней есть критический недостаток, её придумал не Microsoft, поэтому в SharePoint своя библиотек для загрузки скриптов. Называется она Script On Demand.

Script On Demand

Вся библиотека содержится в классе SP.SOD в файле init.js. Script On Demand спроектирован как неинтрузивная библиотека, в отличие от requirejs, то есть скрипты будут работать и без нее. Это важно в App Parts, которые по сути отдельные страницы в iframe. Там нет смысла откладывать загрузку скриптов.

Документация по SP.SOD есть на MSDN, но она там, мягко говоря, ужасная. В проекте SPTypeScript есть качественные определения типов для SP.SOD, они будут более полезны (SP.Init.d.ts).

Добавление скриптов на страницу

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

У контрола ScriptLink несколько атрибутов:

  • Name – указывает имя скрипта. Если указать только имя файла, то скрипт будет загружаться из _layouts. Поддерживаются url tokens, такие как ~site и ~sitecollection.
  • Localizable – если стоит значение true и указано только имя скрипта, то скрипт будет за загружаться из _layouts/{langId}.
  • LoadAfterUI – если стоит значение true, скрипт будет добавлен в конец страницы (независимо от местоположения контрола ScriptLink) и загрузка начнется после рисования всего интерфейса.
  • OnDemand – если указано значение false или атрибут отсутствует, то генерируется такая разметка:
    <script type="text/javascript">
    // <![CDATA[
    document.write(
        '<script type="text/javascript" src="script.js"></' 
        + 'script>');
    // ]]>
    </script>
    
    
    Если же указано значение true, то генерируемый код такой:
    <script type="text/javascript">
    RegisterSod("script.js", "script.js");
    </script>
    
    
    Метод RegisterSod это SP.SOD.registerSod. Загрузка такого скрипта не начнется, пока не будет вызвана явно с помощью класса SP.SOD.

Если вы делаете серверную веб-часть или контрол без разметки, то вам могут пригодиться статические методы класса ScriptLink:

К сожалению класс ScriptLink не доступен в Sandbox, поэтому обязательно необходимо пользоваться классом SP.SOD.

Внимание: никогда в веб-частях и контролах не генерируйте тег script с атрибутом src. Ваш контрол или веб-часть могут быть добавлены более одного раза на страницу и скрипты будут загружаться несколько раз. Если же вы вызовете SP.SOD.registerSod несколько раз, то скрипт будет загружен только один раз (свойство идемпотентности).

SP.SOD.registerSod(fileName: string, url: string): void;

В первом параметре указывается имя зависимости, а во втором – url скрипта.

Ожидание загрузки скрипта

Если вы воспользовались ScriptLink с атрибутом OnDemand=false, и вам надо дождаться окончания его загрузки, чтобы вызвать свой код, то вам нужен метод

SP.SOD.executeOrDelayUntilScriptLoaded(func: () => void , depScriptFileName: string): bool

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

Вызов этой функции часто нужен для ожидания окончания загрузки файла sp.js, содержащего JSOM.

SP.SOD.executeOrDelayUntilScriptLoaded(function() {
    var ctx = SP.Context.gt_current();
    //Do something
}, 'sp.js');

Увы, эта функция теряет this.

Загрузка по требованию

Если вам необходимо загрузить скрипт по требованию, то для этого есть целых два метода:

  • SP.SOD.execute(fileName: string, functionName: string, args?: any[]): void;
  • SP.SOD.executeFunc(fileName: string, typeName: string, fn: () => void ): void;

Пример вызовов (результат одинаковый):

SP.SOD.executeFunc('mQuery.js', 'm$', function() {
     m$.ready(function (){ });
}

SP.SOD.execute('mQuery.js', 'm$.ready', [function (){ }] );


Есть еще один метод, который загружает сразу несколько скриптов:
SP.SOD.loadMultiple(keys: string[], fn: () => void): void;

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

Зависимости между скриптами

Чтобы сделать зависимость между скриптами надо вызвать метод:

SP.SOD.registerSodDep(fileName: string, dependentFileName: string): void;

В дальнейшем, если вызвать загрузка скрипта с именем fileName, то перед ним будет загружен скрипт с именем dependentFileName. Эта функция идемпотентна, как и SP.SOD.registerSod.

Использование SOD в своих скриптах

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

SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs(scriptFileName: string): void;

Так как SOD неинтрузивная библиотека, то хорошим тоном будет писать так:

if ( SP && SP.SOD ) {
    SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs("script.js");
}

Если вы используете внешние скрипты и хотите их подключить к SOD, то потребуется написать хелпер (typescript):

function loadExternalScript(key: string, scriptPath: string) {
    var scriptNode = document.createElement('script');
    scriptNode.type = 'text/javascript';
    scriptNode.src = scriptPath;

    var headNode = document.getElementsByTagName('head');
    if (headNode[0] != null)
        headNode[0].appendChild(scriptNode);

    var callback = (e: Event) => {
        SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs(key);
    };
    scriptNode.onreadystatechange = callback;
    scriptNode.onload = callback;
}

SOD и MDS

SharePoint 2013 принес еще одно новшество- Minimal Download Strategy. Эта стратегия заставляет браузер перезагружать не всю страницу, а частями. Такая загрузка снижает трафик, но плохо влияет на скрипты. Потому что теперь страница может быть обновлена без перезагрузки скриптов.

Для того, чтобы функция была вызвана после ajax перезагрузки страницы (без перезагрузки скриптов), надо зарегистрировать её с помощью

function RegisterModuleInit(scriptFileName: string, initFunc: () => void ): void;

Первый параметр – url скрипта, указанный в SOD, второй – функция, которую надо вызывать при ajax перезагрузке.

Ковыряя исходники скриптов SharePoint, я нашел интересную вещь. Функция SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs сама вызывает RegisterModuleInit. В качестве initFunc передается функция с именем $_global_!scriptName!. !scriptName! формируется путем отрезания расширения (после последней точки) и заменой всех точек на символы подчеркивания. Но это работает только для скриптов в _layouts/15.

Publish\Subscribe

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

Publish\Subscribe состоит из трех методов:

  • SP.SOD.notifyEventAndExecuteWaitingJobs(eventName: string, args?: any[]): void;
    Этот метод вызывает события с указанными параметрами.
  • SP.SOD.executeOrDelayUntilEventNotified(func: Function, eventName: string): bool;
    Эта функция создает подписку на событие с параметрами и вызывается если событие уже наступило.
  • SP.SOD.delayUntilEventNotified(func: Function, eventName: string): void;
    Эта функция только создает подписку.

Заключение

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



Машина разработчика SharePoint в Windows Azure

Ранее я занимался разработкой под SharePoint  на компьютере, стоящим под столом. На нем была развернута виртуальная ферма. Последнее время я всю разработку перенес в облако. Apps отлаживаю на Office 365, серверный код SharePoint создаю и отлаживаю на виртуальной машине в Windows Azure, код храню в Team Foundation Service.

Office 365 и Team Foundation Service – это SaaS, поэтому не вызывает проблем использование и расчет эффективности. А вот виртуалки в Windows Azure (Iaas) вызывают много вопросов.

Почему облака

Доступность

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

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

Гибкость

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

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

Бесплатно

Как владельцу MSDN подписки мне это ничего не стоит. Если же вам все таки придется платить, то расчеты в конце.

Конфигурация

Для того чтобы поднять полноценную среду для разработки вам нужны: контроллер домена с DNS сервером, SQL Server и собственно сам SharePoint. Для целей демонстрации еще понадобится Office Web Apps Server. Причем DC и WebApps должны стоять отдельно, а SQL Server и SharePoint можно совместить. Для разработки это удобно, так как это увеличивает утилизацию ресурсов и не надо по отдельности выключать виртуалки.

А теперь по порядку:

Сеть

Чтобы виртуалки видели друг друга, для начала надо создать виртуальную сеть. Все виртуалки начинают получать адреса по порядку из этой сети. Причем начиная с xx.xx.xx.4 и в порядке включения. В настройках сети также задаются адреса внутренних DNS серверов. Руками править настройки сети в Azure нельзя! Это означает что DNS серверы должны быть включены всегда или должны включаться в определенном порядке, чтобы из IP адреса не менялись.

У меня один DNS сервер на контроллере домена на XS виртуалке и он всегда включен.

Контроллер домена

Тут все просто. Одна XS виртуалка и дополнительный диск для данных домена. Установлены роли AD DS и DNS. Если понадобятся сертификаты, то надо добавить AD CS.

Машина разработчика

Я использую XL виртуалку, на которой стоит SQL Server и SharePoint 2013. На борту 8 ядер (честных, не виртуальных) и 14 ГБ памяти. Для целей разработки этого более чем достаточно.

Но самое главное при работе SharePoint это диски. Быстродействие фермы SharePoint упирается в первую очередь в диски. Когда вы читаете документацию по развертыванию SQl Server и SharePoint там указаны требования к объему дисков, неявно предполагая что все это разные физические диски или как минимум разные LUNы на СХД. Когда разворачивается тестовая ферма или ферма для разработки, то все виртуальные диск попадают на один физический и все дико тормозит.

Диски в Windows Azure это блобы в Azure Storage. Максимальня пропускная способность одного блоба – 60 мегабайт в секунду(http://blogs.msdn.com/b/windowsazure/archive/2012/11/02/windows-azure-s-flat-network-storage-and-2012-scalability-targets.aspx). Внутри виртуальной машины файлы между дисками копируются со скоростью 10 мегабайт в секунду. Но самое главное что для масштабирования IO вы можете добавить столько дисков сколько нужно.

Для SharePoint+SQL Server оптимальной будет такая конфигурация:

  • Диск для данных SQL (можно масштабировать по количеству баз)
  • Диск для логов SQL (можно масштабировать по количеству баз)
  • Диск для tempdb
  • Диск для текстовых логов IIS и SharePoint
  • Диск для индекса поиска

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

Такая конфигурация работает быстрее, чем на домашнем компьютере.

Тестирование

Для тестов я поднял еще одну машину с Visual Studio и сделал нагрузочный тест для SharePoint. Увы базы SharePoint у меня пустые и кастома почти нет, поэтому результаты тестирования не очень показательны.

Нагрузочный тест открывал главные страницы сайтов разных шаблонов. Нагрузка росла равномерно с 10 виртуальных пользователей до 200.

Результаты нагрузочного теста:

  • 100 requests per senond
  • Все уперлось в процессоры (75% IIS, 25% SQL)
  • Памяти свободной – 1,5 гб (потому что базы пустые)
  • Диски загружены на 15% максимум
  • Примерно на 70 виртуальных пользователях некоторые страницы стали отвечать более 10 секунд
  • IIS ошибок не отдавал

Интересные наблюдения:

  • Для WFE в SharePoint очень важны процессоры, так как страницы “тяжелые” и требуют много ресурсов на рисование.
  • WFE дает нагрузку на диск из-за записи текстовых логов (около 3 мб\сек) в режиме Verbose.
  • Для SQL очень важны диски. Даже в сценарии открытия страниц нагрузка на LOG файлы БД около 1,5 мб\сек.
  • Поиск SharePoint все кеширует в памяти, поэтому для серверов поиска очень важен объем памяти. А также диск, он влияет на скорость индексирования.

Стоимость

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

Расходы:

  • DC – виртуалка XS, работает постоянно – 491 рублей в месяц.
  • SharePoint – виртуалка XL, работает в среднем 172 часа в месяц (8x5) - 4086,72 рублей в месяц.
  • 100гб данных – 231 рублей в месяц.
  • Трафик и тразакции за месяц на разработческой машине стоят меньше 100 рублей.

Итого – чуть меньше 5 тысяч рублей в месяц. С подпиской MSDN дешевле почти в 2 раза.

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

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

Для команд разработки SharePoint иметь машины на Azure может быть очень выгодно. Сильно повышается мобильность. Можно сэкономить на использовании общего SQL Server на несколько разработчиков, ведь диски масштабируются практически бесплатно.

Заключение

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



Скрытая стоимость решений на SharePoint

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

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

Из чего складывается скрытая стоимость

Затраты на ожидание

Первый пункт самый банальный. Любая компьютерная система имеет время реакции на действия пользователя. Самое простое – время открытия страницы. Если пользователь открывает 20 страниц в час, то за день выходит 160 страниц. Если вместо двух секунд страница открывается 6 секунд, то за день только в ожидании страниц пользователь проводит 10 минут. Для 100 пользователей это уже значительное время. А время = деньги.

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

Слишком много ручных действий

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

Поиск информации

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

Исследования показывают, что сотрудники, занимающиеся обработкой информации тратят на её поиск от 15% до 35% времени. Источник: http://www.kmworld.com/Articles/Editorial/Features/The-high-cost-of-not-finding-information-9534.aspx.

Обходные пути

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

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

Обращения в службу поддержки

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

Доработки

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

Стоимость апгрейда

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

Стоимость обслуживания решения

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

Как бороться со скрытыми затратами

Большинство скрытых затрат происходят от дефектов решения, которые невозможно выявить на приемо-сдаточных испытаниях. Чаще всего это:

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

А теперь собственно как бороться:

Пилотные проекты

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

Ранее прототипирование

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

Слабосвязные сервисы

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

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

Не пытаться покрыть 100% потребностей

Это очень важно. SharePoint, как и любая другая платформа имеет свои ограничения, то сделать на нем можно все что угодно, но некоторые вещи будут крайне дорогими. Тут нужно применять правило Парето: 20% усилий дают 80% результата. Остальные 80% лучше потратить на создание других сервисов.

Придерживайтесь best practices

Даже в официальной документации по платформе описаны сотни рекомендаций как надо делать. Кроме того множество книг содержат эти самые рекомендации. Отступая от этих рекомендаций вы повышаете скрытые расходы ваших решений на SharePoint. Нужна очень веская причина чтобы отступать от рекомендаций.

Design review

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

Проверка решений

По возможности делайте аудит кода. Для этого существуют инструменты, например SPCAF (http://www.spcaf.com/). А особо сложных случаях также можно привлечь консультантов.

Имейте все исходники и документацию

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

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

Заключение

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

Исследования множества проектов разработки (Shull defects paper) говорят о том, что 20%-80% стоимости разработки занимает переделывание работы, связанное с исправлением дефектов. Разброс большой, точная величина зависит от уровня зрелости разработки у исполнителя.

Ранее я приводил таблицу результативности методов устранения дефектов (http://gandjustas.blogspot.com/2013/07/code-review-vs-testing.html). Прототипирование, инспекции дизайна и кода показывают одни из лучших результатов. В совокупности они могут дать до 95% устранения дефектов до релиза. Правильный подход к разработке может сократить общие затраты на создание решения более чем в два раза, добавив незначительные затраты на прототипирование и инспекции.

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

В итоге делать хорошие решения получается быстрее и выгоднее для обоих сторон.



Связанные элементы в SharePoint 2013

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

Копая JSOM, я недавно обнаружил, что в SharePoint 2013 есть такой функционал.

“Изкаропки” он доступен в списке задач. У каждой задачи есть “связанные элементы”.

image

При нажатии на “добавить связанный элемент” появляется стандартный asset picker

image

Можно выбирать любой элемент в пределах коллекции сайтов.

Внутренности “связанных элементов”

“Связанные элементы” это кастомное поле с ID равным значению Microsoft.SharePoint.SPBuiltInFieldId.RelatedItems. Это поле скрытое и добавить его в список из интерфейса не получится. Но в решении вы совершенно спокойно можете добавить это поле в тип контента.

Сам касс поля определен в сборке Microsoft.SharePoint и доступен, в том числе, в Foundation. Для работы с полем доступны только клиентские API, серверный класс для них помечен как internal.

На клиенте можно обращаться с помощью классов SP.RelatedItemManager в sp.js (http://msdn.microsoft.com/en-us/library/jj838582.aspx) и Microsoft.SharePoint.Client.RelatedItemManager в сборке Micrsosoft.SharePoint.Client (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.relateditemmanager.aspx).

Если интересна реализация поля, то смотрите с помощью IlSpy класс Microsoft.SharePoint.RelatedItemManager в сборке Microsoft.SharePoint. Рендеринг поля описан в файле sp.ui.relateditems.js

Реализация поля предельно простая – в текстовом поле сохраняется сериализованный в json массив элементов Microsoft.SharePoint.RelatedItem. Есть ограничение – не более 9 связанных элементов. Скорее всего оно связано с необходимостью secutrity trimming ссылок на связанные элменты, а это делается крайне медленно в SharePoint. Для security trimming ссылок в ленте новостей используется поиск+кеширование, но функционал “связанных элементов” рассчитан на работу в foundation и не может использовать такие возможности.

Применение

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

Наибольший интерес “связанные элементы” представляют как пример качественно сделанного расширения платформы. Оно включает в себя Custom Field Type с контролом, API на сервере и на клиенте, рендеринг поля в формах и использование asset picker. Если будете делать что-то подобное, то изучите реализацию “связанных элементов”.



Code Review vs Testing

Почти все знают, что баг в программе, исправленный на этапе использования, стоит примерно в 100 раз дороже, чем исправленный до использования. Кто не верит – может почитать результаты исследования Shull defects paper.

Если спросить программистов какой метод исправления поиска и исправления багов наиболее эффективный, то большинство ответит - “тестирование”. И будут неправы…

Эффективность различных методов устранения ошибок

В книге МакКоннелла CodeComplete есть статистика (да-да, все её читали, но никто сходу не может вспомнить что там написано), которая разрывает мозг многим апологетам тестов.

Методика

Результативность в среднем

Regression test 25%
Informal code reviews 25%
Unit test 30%
New function (component) test 30%
Integration test 35%
Low-volume beta test (< 10 users) 35%
Informal design reviews 35%
Personal desk checking of code 40%
System test 40%
Formal design inspections 55%
Formal code inspections 60%
Modeling or prototyping 65%
High-volume beta test (> 1000 users) 75%

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

Как делать review

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

  • Чтобы проводить инспекции нужны чек-листы.
  • Темп code review составляет 120-200 строк в час.
  • Инспекторов должно быть как минимум два.
  • Должны быть адекватно описаны требования к коду: быть полными и не содержать противоречий и неточностей.
  • Код должен компилироваться.
  • Код должен быть проверен разработчиком, как минимум выполнять основные сценарии на его машине.

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

Как повысить эффективность code review

Средняя продолжительность продуктивного писания кода – 4-5 часов в день. То есть 3-4 часа в день программист не занимается написанием кода, или занимается, но лучше бы этого не делал. Можно скорректировать время работы программистов, чтобы 4 часа в день они писали код, два часа делали review, еще два часа занимались проектированием, митингами и административными задачам. То есть review получается практически бесплатно.

Команда в 3-4 человека будет вполне успевать проводить review написанного за день кода в оставшиеся 2 часа после кодирования.

Значительную часть review можно автоматизировать, есть множество инструментов, которые проверяют качество кода.

Если все так круто, то почему же все занимаются тестированием?

Ответ на этот вопрос я долго искал, пока не наткнулся на презентацию Эрика Липперта о психологических аспектах анализа кода (http://www.slideshare.net/Coverity/the-psychology-of-c-analysis-24025354). Несмотря на то, что в презентации рассказывается об автоматизированном анализе, причины недоверия более чем верны для code review.

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

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

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

Заключение

Несколько статей про code review, в них есть много интересных ссылок на исследования и книги:

Немного про SharePoint. Джентльменский набор для анализа кода:

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