Итоги 2014 года и планы на будущее

2014 год для меня выдался очень бурным. В апреле я покинул компанию АйТеко, где работал менеджером по развитию бизнеса, а до этого архитектором решений. За время работы в АйТеко я приобрёл огромный опыт продажи и создания бизнес-решений, разобрался как работает крупный бизнес (в основном банки и телеком) и понял как можно помогать им делать работу более эффективно.

После айтеко я еще несколько месяцев работал part-time архитектором, параллельно развивая свой бизнес. С июля я работаю исключительно на себя и безмерно этому рад.

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

Рынок в 2014-2015 году

Еще с начала 2014 года была очевидна тенденция снижения размеров проектов. Мало кто заказывал типичные корпоративные порталы с длинными циклами планирования и внедрения, все хотели быстро получить результат . В 2015 году эта тенденция усилится из-за экономического кризиса.

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

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

Развертывание ферм SharePoint

Как ни странно самая высокая маржа получилась на развертывании ферм SharePoint. На практике спланировать и развернуть развернуть ферму SharePoint 2013 очень непросто. Встроенный configuration wizard делает от силы треть необходимых настроек, а развертывание на несколько серверов требует недели работы.

Используя правильные инструменты мне удалось разворачивать многосерверные фермы буквально за один день, а развертывание тестовых и разработческих  сред вообще можно выполнить за несколько часов. В итоге я заработал на развертывании SharePoint более 200,000 рублей, потратив суммарно около 5 дней работы.

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

PowerPivot и PowerView

Год назад я начал использовать PowerPivot и PowerView в SharePoint как инструмент разработки решений и это дало просто потрясающий эффект. PowerPivot помог реализовать решения, которые обрабатывают сотни тысяч элементов списков, не написав при этом ни единой строчки серверного кода SharePoint, а PowerView позволил делать отчеты за считанные минуты. Рукопашная реализация всех расчетов заняла бы несколько недель чистого времени на разработку и пару месяцев на отладку и внедрение.

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

Сообщество

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

Кстати для тех, кто дочитал до сюда, бонус – записи с декабрьской встречи юзер-группы - http://www.youtube.com/playlist?list=PLfB6mTkgdUsILmayFAM41h0Wr8YQyE7ma

В онлайн-сообществе на facebook количество участников подбирается к 500, надеюсь и дальше будет расти, пополняясь интересным контентом.

Мне нужен партнер

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

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

Если вам интересно работать в таком режиме - пишите.

Мне нужен специалист по SharePoint, с навыками программирования C#, JavaScript и PowerShell, готовый изучать другие языки и технологии, например Microsoft Dynamics, BizTalk и даже 1C, а в дальнейшем сможет развиваться как менеджер.



Подборка материалов о серверной оптимизации ASP.NET

В процессе подготовки семинара по оптимизации, который пройдет 30 октября 2014 года (регистрация тут - http://gandjustas.timepad.ru/event/150915/), я собрал ранее опубликованные материалы по серверной оптимизации ASP.NET приложений.
Серия постов о кешировании на хабре:
Оптимизация работы с данными:
Какие темы вам еще будут интересны?


7 способов улучшить поля в формах SharePoint 2013

Кастомизация форм – очень больная тема в SharePoint. InfoPath фактически умер, новые способы кастомизации появятся не раньше следующего релиза (назначенного на конец 2015 года), а для использования SPServices нужен jQuery старой версии, что само по себе несет проблемы, так еще и требует знания отображаемых имен полей, что делает решение ненадежным. Подробнее в моем курсе по клиентской разработке SharePoint.

Создавая TypeScript-определения для клиентской библиотеки SharePoint  сделал несколько примеров полей. Недавно я провел большой рефакторинг и выделил кастомные поля в отдельные, повторно используемые функции.

Все функции содержатся в файле typescripttemplaes.ts. Тем, кто не пользуется TypeScript (зря!), можно скачать .js файл в том же каталоге.

Как пользоваться typescripttemplates:

  1. Скачать файл и добавить .js в проект
  2. Сделать свой файл скрипта для полей, такого вида:
    module _ {
        function init() {
            CSR.override()
                .lookupAddNew("Master", "Add New Master item", true)
                .register();        
        }
    
        SP.SOD.executeOrDelayUntilScriptLoaded(init, "typescripttemplates.ts");
    
        SP.SOD.executeOrDelayUntilScriptLoaded(function () {
            RegisterModuleInit(SPClientTemplates.Utility.ReplaceUrlTokens("~site/YOUR_SCRIPT_PATH.js"), init);
        }, "sp.js");
    } 
  3. Вписать адрес скрипта в ReplaceUrlTokens и вызовы функций между .override() и .register()
  4. В атрибут JSLink поля\формы\типа контента вписать строку такого вида: “~site/PATH/typescripttemplates.js|~site/YOUR_SCRIPT_PATH.js”.

Итак сами функции:

№1 Установка начального значения поля в формах

CSR.override()
   .setInitialValue("FieldInternalName", ANY_VALUE)
   .register();      

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

№2 Скрытие поля

CSR.override()
   .makeHidden("FieldInternalName")
   .register();      

Скрывает поле на форме, в представлении, и даже в режиме редактирования таблицы.

№3 Установка поля в Read-Only в формах

CSR.override()
   .makeReadOnly("FieldInternalName")
   .register();      

Заменяет контрол ввода на контрол отображения. Пока не работает в для поля выбора пользователя.

№4 Вычисляемое значение поля

CSR.override()
   .computedValue("Title", function(x) {return SPClientTemplates.Utility.ParseLookupValue(x).LookupValue; }, "SOME_LOOKUP_FIELD")
   .register();      

Автоматически задает значение поля при изменении в связанном поле.

№5 Добавление ссылки на добавление нового элемента в Lookup

CSR.override()
   .lookupAddNew("Master", "Add New Master item", true)
   .register();      

Добавляет рядом с Lookup-полем ссылку, которая открывает форму добавления в связанный список. Последний параметр задает открывать ли форму в диалоге или переходом на страницу формы

№6 Фильтрация Lookup

CSR.override()
   .filteredLookup("Master", '<BeginsWith><FieldRef Name ="Title" /><Value Type = "Text" >{Title}</Value></BeginsWith>')
   .register();      

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

№7 Lookup на основе поиска

CSR.override()
   .seachLookup("LookupFieldInternalName")
   .register();      

Заменяет стандартный элемент выбора на компонент autofill, входящий в SharePoint. Для получения связанных элементов используется поиск. Будет работать даже для очень больших списков. В ближайшее время будет добавлена возможность указывать запрос, который выполняется при получении элементов.

Для этого поля надо в JSLink добавить ссылки на файлы autofill.js и sp.search.js – “~site/PATH/typescripttemplates.js|~site/YOUR_SCRIPT_PATH.js|autofill.js(d)|sp.search.js(d)”

Заключение

Качайте, пользуйтесь, пишите фидбек здесь и на сайте проекта - http://sptypescript.codeplex.com/workitem/list/basic. Кроме указанных выше готовых контролов, есть еще куча хелперов, которые вам помогут делать свои шаблоны полей.

Если хелперы будут популярны, то я выложу библиотеку в NuGet.



Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server с помощью LINQ

Доклад с таким длинным и непонятным названием я читал на SQL Server User Group 10 сентября в Москве. Ниже слайды запись доклада:

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

CREATE PROCEDURE [dbo].[GetTransactionsByShipDate]
    @shipDate datetime
AS
    SELECT t.Id, t.ProductId, t.TransactionDate 
       from Transactions t
    where
        (@shipDate is not null 
          and t.ShippedDate = @shipDate) 
     or (@shipDate is null 
          and t.ShippedDate is null)

Эта процедура подвержена parameter sniffing problem. Проблема заключается в том, что план процедуры генерируется один раз при первом вызове с учетом фактических параметров при вызове. Если при первом вызове ShipDate был NULL (низкая селективность), то сгенерируется план с Index Scan. Если же первый вызов был с конкретным значением даты, то получится Index Seek, который будет неэффективно работать для значений с низкой селективностью.
Простой тест:
DBCC FREEPROCCACHE
GO

EXEC    [dbo].[GetTransactionsByShipDate] NULL
GO

declare @shipdate datetime = getdate()
EXEC    [dbo].[GetTransactionsByShipDate] @shipdate
GO

DBCC FREEPROCCACHE
GO

declare @shipdate datetime = getdate()
EXEC    [dbo].[GetTransactionsByShipDate] @shipdate
GO

EXEC    [dbo].[GetTransactionsByShipDate] NULL
GO

Результаты:
image
Как видите план оказывается далеко не оптимальным в обоих случаях.
А с помощью Linq можно написать так:
private static IQueryable<Transaction> GetValues(
    IQueryable<Transaction> query, 
    DateTime? dateTime)
{
    if (dateTime.HasValue)
    {
        return query.Where(t => t.ShippedDate == dateTime.Value);
    }
    else
    {
        return query.Where(t => t.ShippedDate == null);
    }
}
Тогда буду сгенерированы два разных запроса, каждый со своим, оптимальным для данного запроса, планом.
Более того, такая оптимизация для null value встроена в провайдер Linq2DB. Там можно непосредственно nullable значения подставлять в linq.
Более того, можно использовать filtered index, когда больше 2% значений по индексируемому полю равны NULL.


Записи докладов по Business Intelligence c DevCon 2014

На конференции DevCon, которую ежегодно организует Microsoft, в 2014 году я выступал аж с двумя докладами, оба были на тему Business Intelligence в SharePoint.

Недавно были опубликованы видеозаписи. Выложу их в блоге, чтобы проще было найти.

Первый доклад по Power Pivot в SharePoint 2013 (on-premises), в котором я показываю пример мини-erp решения для управленя отделом, которое можно собрать за несколько часов совершенно без программирования.

Второй доклад посвящен возможностям PowerBI в Office 365. Особое внимание было уделено инструменту Power Query, его использованию в Excel, а также настройке гибридной среды для получения доступа из облака к данным on-premises.

А вы используете в своей работы BI инструменты SharePoint? Напишите в комментах в каких сценариях применяли или почему не применяли.