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

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/


Релиз SPCAF Contrib

Для тех кто не в курсе что такое SPCAF. SPCAF – аббревиатура SharePoint Code Analysis Framework, инструмент позволяющий проводить проверки кода решений SharePoint и собирать полезные метрики. SPCAF состоит из четырех компонент: SPCop, SPMetrics, SPInventory, SPDependency. Первый компонент распространяется отдельно и бесплатно. Весь SPCAF стоит 2500 евро (очень дорого).
SPCAF создавался для крупных компаний, которые работают с кучей подрядчиков, и для них очень актуальна проблема стабильности фермы в таких условиях. Проблемы, с которыми программисты сталкиваются во время разработки, в базовом наборе правил SPCop адресованы очень слабо.
Поэтому мы решили создать набор правил для SPCop, чтобы облегчить процесс разработки решений и ловить многие проблемы до того, как они проявятся во время тестирования или промышленной эксплуатации. Также создали правила, которые подсказывают best pratices при разработке решений.
Кстати мы это:

Как использовать

1. Поставить SPCop из галереи расширений Visual Studio
image
2. Скачать spcafcontrib.dll и положить в папку C:\Program Files (x86)\SPCOPCE\
3. Запустить анализ в Visual Studio
image
4. Анализируйте результаты и настраивайте правила
image

Заключение

Сайт SPCAF - http://www.spcaf.com/
Ссылка на сайт проекта - http://spcafcontrib.codeplex.com/
Презентация - http://www.slideshare.net/gandjustas/sharepoint-code-quality
Ставьте, используйте, оставляйте feedback на сайте проекта.


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

Untitled

Первая часть этой серии была написана примерно полтора года назад, после этого появился SharePoint 2013, в котором добавили очень много возможностей для использовании поиска в решениях. Но недавний опрос в сообществе (https://www.facebook.com/groups/sharepointrussian/permalink/514677285314072/?stream_ref=2) показал, что наиболее популярной версией до сих пор является SharePoint 2010.

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

DataFormWebPart

Стандартная веб-часть SharePoint позволяет использовать различные источники данных и формировать разметку с помощью XSL. Источник данных описывается с помою класса наследника System.Web.UI.DataSourceControl. В разметке страницы или .webpart файле можно указать какой DataSource использовать в веб-части.

SearchDataource

Для начала создадим DataSource, который возвращает результаты поискового запроса. На MSDN есть инструкция по созданию класса DataSource - http://msdn.microsoft.com/RU-RU/library/92e191zc(v=vs.90)

public class SearchDataSource: DataSourceControl
{
    protected override DataSourceView GetView(string viewName)
    {
        return new SearchDataSourceView(this);
    }

    public string QueryText { get; set; }

    public string SelectProperties { get; set; }        
}
Основная работа делается в классе SearchDataSourceView, наследнике DataSourceView.
class SearchDataSourceView: DataSourceView
{
    SearchDataSource dataSource;

    public SearchDataSourceView(SearchDataSource dataSource): base(dataSource,"")
    {
        this.dataSource = dataSource;
    }

    public override bool CanPage
    {
        get
        {
            return true;
        }
    }

    public override bool CanSort
    {
        get
        {
            return true;
        }
    }

    public override bool CanRetrieveTotalRowCount
    {
        get
        {
            return true;
        }
    }

    protected override System.Collections.IEnumerable ExecuteSelect(DataSourceSelectArguments arguments)
    {
        var query = GetQuery(arguments.SortExpression);

        query.StartRow = arguments.StartRowIndex;
        query.RowLimit = arguments.MaximumRows;

        var results = query.Execute()[ResultType.RelevantResults];
        arguments.TotalRowCount = results.TotalRows;
        return results.Table.DefaultView;
    }

    private KeywordQuery GetQuery(string sortExpression)
    {
        /* omited for clarity */
    }
}

Основной метод класса – ExecuteSelect, он должен возвращать IEnumerable, поддерживающий TypeDescriptor, например DataView. Про TypeDescriptors я писал ранее – http://gandjustas.blogspot.ru/2011/08/blog-post_22.html. Класс DataSourceView может поддерживать разбиение на страницы и сортировку, это определяется свойствами, которые я переопределил в начале.

Код создания запроса:

private KeywordQuery GetQuery(string sortExpression)
{
    var query = new KeywordQuery(SPContext.Current.Site);
    query.QueryText = this.dataSource.QueryText;
    query.ResultTypes = ResultType.RelevantResults;

    if (!string.IsNullOrEmpty(this.dataSource.SelectProperties))
    {
        query.SelectProperties.Clear();
        foreach (var property in this.dataSource.SelectProperties.Split(','))
        {
            query.SelectProperties.Add(property.Trim());
        }
    }

    if (!string.IsNullOrEmpty(sortExpression))
    {
        query.SortList.Clear();
        foreach (var sort in sortExpression.Split(','))
        {
            if (sort.EndsWith(" DESC"))
            {
                query.SortList.Add(sort.Substring(0, sort.IndexOf(" DESC")), SortDirection.Descending);
            }
            else
            {
                query.SortList.Add(sort, SortDirection.Ascending);
            }
        }
    }

    return query;
}

Этот код заполняет базовые параметры, запрашиваемые свойства и параметры сортировки.

Настройка веб-части

Добавляем веб-часть на страницу

image

 

Далее заменяем DataSource и вставляем identity transform

image

Директиву Register нужно вставлять прямо в раздел DataSource. В XSL надо вставить Identity Transform, чтобы получить данные в виде XML :

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:template match="/"  >
        <xmp>
            <xsl:copy-of select="." />
        </xmp>
    </xsl:template>
</xsl:stylesheet>

В результате получим такое:

image

Далее можно скопировать полученный XML и сделать необходимый XSL в Visual Studio или в SharePoint Designer.

Например так:

image

Создаем пакет решения

Чтобы завернуть полученный результат в WSP надо экспортировать веб-часть с сайта. Получившийся .webpart файл включить в решение. Это все.

Причем можно деплоить сборку с DataSource в farm solution, а .webpart файлы в sandbox.

Для конкретных задач можно расширить функционал:

  • Добавить обработку параметров DataSource. Параметры позволяют использовать значения QueryString, связи между веб-частями и другие внешние факторы. Также можно создавать свои параметры.
  • Сделать аналогичный DataSource для RefinementResults, чтобы получать статистику. Что очень часто нужно для главной страницы порталов.

Если вам нужна веб-часть в одном экземпляре (что бывает чуть менее, чем всегда), то можно не париться с сохранением .webpart и ковырянием в SharePoint Designer. Достаточно просто сделать наследника DataFormWebPart и переопределить метод GetDataSouce. При этом можно также переопределить XSL, чтобы он всегда указывал на файл в виртуальной файловой системе. Это значительно облегчит сопровождение решения.

Заключение

Как обычно исходники можно найти на http://spsamples.codeplex.com. Также сделал релиз: https://spsamples.codeplex.com/releases/view/117762.

Качайте, смотрите, изучайте, интегрируйте в свои решения.



Восприятие SharePoint

Пост-перевод http://veroniquepalmer.com/2014/01/16/your-sharepoint-perception/

Не правда ли, что мы склонны видеть мир через через призму нашего опыта, но не так, как на самом деле. Возьмите SharePoint например ...

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

И так можно продолжать очень долго.

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

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

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

perception



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

НеНаступи_small

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

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

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

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

Вывод

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