IDisposable - что ваша мама не говорила об освобождении ресурсов. Что не так с IDisposble.

Это перевод первой части статьи https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About. Статья была написана в 2008 году. Спустя 10 лет почти не потеряла актуальности.

Детерминированное освобождение ресурсов - необходимость

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

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

Угадайте какой рекомендации не следует рантайм .NET, и как следствие все языки на его базе?

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

.NET поддерживает недетерминированное освобождение ресурсов с помощью метода Finalize, который имеет специальное значение. Для детерминированного освобождения ресурсов Microsoft также добавил интерфейс IDisposable (и другие классы, которые мы рассмотрим позже). Тем не менее для рантайма IDisposable это обычный интерфейс, как и все остальные. Такой статус “второсортного” создает некоторые сложности.

В C# “детерминированное освобождение для бедных” может быть реализовано с помощью операторов try и finally или using (что почти тоже самое). В Microsoft долго обсуждали делать ли счетчики ссылок или нет, и мне кажется, что было принято неверное решение . В результате для детерминированного освобождение ресурсов нужно использовать неуклюжие конструкции finally\using или прямой вызов IDisposable.Dispose, что чревато ошибками. Для С++ программиста, который привык использовать shared_ptr<T> оба варианта не привлекательны. (последнее предложение дает понять откуда у автора такое отношение - прим. пер.)

IDisposable

IDisposable - решение для детерминированного освобождения ресурсов, предлагаемое Miсrosoft. Одно предназначено для следующих случаев:

  • Любой тип владеющий управляемыми (IDisposable) ресурсами. Тип обязательно должен владеть, то есть управлять временем жизни, ресурсов, а не просто ссылаться на них.
  • Любой тип, владеющий неуправляемыми ресурсами.
  • Любой тип, владеющий как управлемыми, так и неуправляемыми ресурсами.
  • Любой тип, унаследованный от класса, реализующего IDisposable. Я не рекомендую наследоваться от классов, владеющих неуправляемыми ресурсами. Лучше использовать вложение.

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

Сложности IDisposable - удобство использования

Объекты IDisposable использоватькорректно довольно громоздко. Использование объекта нужно обернуть в конструкцию using. Плохо то, что C# не позволяет использовать using с типом, не реализующим IDisposable. Поэтому программист должен каждый раз обращаться к документации чтобы понять надо ли писать using, или просто писать using везде, а потом стирать там, где ругается компилятор.

Managed C++ в этом отношении гораздо лучше. Он поддерживает стековую семантику для ссылочных типов, которая работает как using только для тех типов, где это необходимо. C# мог бы выиграть от возможности писать using с любым типом.

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

IDisposable вместо подсчета ссылок несет другую проблему - определение владельца. Когда в C++ последня копия shared_ptr<T> выходит из области видимости ресурсы освобождаются сразу же, не надо думать кто должен освобождать. IDisposable напротив заставляет программиста определять кто “владеет” объектом и ответственнен за его освобождение. Иногда владение очевидно: когда один объект инкапсулирует другой и сам реализует IDisposable, следовательно отвечает за освобождение дочерних объектов. Бывает время жизни объекта определяется блоком кода и программист просто использует using вокруг этого блока. Тем не менее существует много случаев, где объект может быть использован в нескольких местах и его время жизни определить сложно (хотя в этом случае подсчет ссылок справился бы прекрасно).

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

Добавление IDisposable к классу и убирание IDisposable из списка реализуемых интерфейсов - это ломающее изменение. Клиентский код, который не ожидает IDisposable, то не освободит ресурсы, если вы добавите IDisposable к одному из своих классов, передаваемых по ссылке на интерфейс или базовый класс.

Microsoft сам столкнулся с этой проблемой. IEnumerator не наследуется от IDisposable, а IEnumerator<T> наследуется. Если коду, принимающему IEnumerator передать IEnumerator<T>, то Dispose не будет вызван.

Это не конец света, но выдает некоторую второстепенную сущность IDisposable.

Сложности IDisposable - проектирование иерархии классов

Самый большой недостаток вызванный IDisposable в области проектирования иерархии - каждый класс и интерфейс должен предсказать понадобятся ли его наследникам IDisposable.

Если интерфейс не наследует IDisposable, но классы реализующие интерфейс реализуют также IDisposable, то конечный код будет или игнорировать детерминированное освобождение, или сам должен проверять реализует ли объект интерфейс IDisposable. Но для этого уже не получится использовать конструкцию using и придется писать уродский try и finally.

Короче говоря IDisposable усложняет разработку повторно используемого софта. Ключевая прчина это нарушение одного из приципов объектно-ориентированного проектирования - разделения интерфейса и реализации. Освобождение ресурсов должно быть деталью реализации. Microsoft решил сделать детерминированное освобождение ресурсов интерфейсом второго сорта.

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

Еще одна сложность IDisposable - коллекции. Часть коллекций “владеют” объектами в них, а часть нет. При этом коллекции сами не реализуют IDisposable. Программист должен не забывать вызывать IDisposable.Dispose для объектов в коллекции или создавать своих наследников классов коллекций, которые реализуют IDisposable чтобы обозначить “владение”.

Сложности IDisposable - дополнительное “ошибочное” состояние

IDisposable может быть вызван явно в любое время, независимо от времени жизни объекта. То есть к каждому объекту добавляется состояние “освобожден”, в котором рекомендуется выбрасывать исключение ObjectDisposedException. Проверка состояния и выбрасывание исключений - дополнительные расходы.

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

Сложности IDisposable - нет гарантий

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

Сложности IDisposable - сложная реализация

Microsoft предлагает патерн для реализации IDisposable. (Ранее был вообще ужасный паттерн, но относительно недавно, после появления .NET 4, документацию поправили, в том числе под влиянием этой статьи. В старых редакциях книг по .NET вы можете найти старый вариант. - прим. пер. )

  • IDisposable.Dispose может быть не вызван вообще, поэтому класс должен включать финализатор чтобы освободить ресурсы.
  • IDisposable.Dispose может быть вызван несколько раз и должен отработать без видимых побочных эффектов. Поэтому необходимо добавлять проверку был метод уже вызван или нет.
  • Финализаторы вызываются в отдельном потоке и могут быть вызваны до того, как IDisposable.Dispose завершит работу. Нобходимо использование GC.SuppressFinalize чтобы избежать таких “гонок”.

Кроме того:

  • Финализаторы вызваются в том числе для объектов, которые выбросили исключение в конструкторе. Поэтому код освобождения должен работать с частично инициализированными объектами.
  • Реализация IDisposable в классе, унаследованном от CriticalFinalizerObject требует нетривиальных конструкций. void Dispose(bool disposing) это вируальный метод и должен испольняться в Constrained Execution Region, что требует вызова RuntimeHelpers.PrepareMethod.

Сложности IDisposable - не подходит для логики Завершения

Завершение работы объекта - часто возникает в программах параллельными или асинхронными потоками. Например класс использует отдельный поток и хочет завершить его с помощью ManualResetEvent. Это вполне можно сделать в IDisposable.Dispose, но может приводить к ошибке если код вызывать в финализаторе.

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

Сборщик мусора .NET использует алгоритм mark-and-sweep. В целом логика выглядит так:

  1. Приостановить все потоки.
  2. Взять все объекты-“корни”: переменные в стеке, статические поля, объекты GCHandle, очередь финализации. В случае выгрузки домена приложения (завершения программы) считается, что переменные в стеке и статические поля не являются корнями.
  3. Рекурсивно пройтись по всем ссылкам из объектов и отметить их как “достижимые”.
  4. Пройтись по всем остальным объектам, у которых есть деструкторы (финализаторы), объявить их достижимыми, и поместить их в очередь финализации (GC.SuppressFinalize говорит GC не делать этого). Объекты попадают в очередь в непредсказуемом порядке.

В фоне работает поток (или несколько) финализации:

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

Теперь должно быть понятно почему нельзя обращаться из финализатора к управляемым ресурсам - вы не знаете в каком порядке вызываются финализаторы. Даже вызов IDisposable.Dispose другого объекта из финализатора может привести к ошибке, так как код освобождения ресурсов может работать в другом потоке.

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

  1. Финализация объектов, унаследованных от CriticalFinalizerObject выполняется после финализации объектов, не-унаследованных от этого класса. Это означает что можно вызывать ManualResetEvent из финализатора пока класс не унаследован от CriticalFinalizerObject
  2. Некоторые объекты и методы особенные, например Console и некоторые методы Thread. Их можно вызывать из финализаторов даже в случае завершения программы.

В общем случае лучше не обращаться к управлемым ресурсам из финализаторов. Тем не менее логика завершения необходима нетривиального софта. В Windows.Forms содержит логику завершения в методе Application.Exit. Когда вы разрабатываете свою библиотеку компонентов лучше всего логику завершения завязать на IDisposable. Нормальное завершение в случае вызова IDisposable.Dispose и экстренное в противном случае.

Microsoft тоже столкнулась с этой проблемой. Класс StreamWriter владеет объектом Stream (в зависимости от параметров конструктора в последней версии - прим. пер.). StreamWriter.Close сбрасывает буфер и вызывает Stream.Close (тоже просиходит если обернуть в using - прим. пер.). Если StreamWriter не закрыт, буфер не сбрасывается и чатсь данных теряется. Microsoft просто не переопределил финализатор, таким образом “решив” проблему завершения. Прекрасный пример нужности логики завершения.

Рекомендую почитать

Много информации о внутреннем устройстве .NET в этой статье почерпнуто из книги “CLR via C#” джеффри Рихтера. Если у вас её еще нет, то купите. Серьезно. Это необходимые знания для любого C# программиста.

Заключение от переводчика

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

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



Ваши вакансии - отстой или как HR-ам привлекать программистов

Этот пост не о технологиях, даже если вы не в курсе что такое SharePoint, то вам это не помешает.

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

1) Компания: ООО «Рога и копыта» ведущая консалтинговая компания в области управления, обладающая 20-летним опытом создания комплексных информационных систем в строительстве, энергетике, нефтегазовой отрасли и др.

2) Требования к кандидату:
•знание и опыт разработки под платформу Microsoft SharePoint Server 2013/2016 в том числе — Web Parts, Features, Master Pages, Custom Controls, Event Receivers, Timer Jobs, Site / List Templates, Workflow;
•знание основных механизмов администрирования SharePoint (Центр Администрирования, PowerShell), опыт работы с ними;
•проектирование структуры контента решения (коллекции сайтов, сайты, списки, поля списков и т.д.);
•навыки использования и реализованные решения на Server Object model, Client object model и REST API;
•знание T-SQL;
• отличное знание платформы .NET (.Net Framework и языка программирования С#);
• отличное знание веб-технологий, опыт разработки (JavaScript + jQuery, HTML, CSS);
• опыт работы c ASP.NET, WCF;
•опыт участия в коммерческих проектах разработок на базе SharePoint 2010/2013;
•умение диагностировать проблемы в работе ПО, вести общение с клиентами при осуществлении проектирования систем, технического сопровождения;
•опыт выполнять диагностику и отладку решений Microsoft SharePoint;

3) Обязанности:
• Проектирование и разработка решений на платформе MS SharePoint 2013/2016 в рамках проектов компании на всех стадиях (от формализации требований до передачи в промышленную эксплуатацию);
• Доработка существующих решений и автоматизация в соответствии с требованиями;
• Разработка решений по интеграции MS SharePoint со сторонними системами;
• Разработка SSOM решений, возможно рассмотреть варианты перевода решений на другую платформу/разработки на другой платформе (CSOM);
• Оценка трудоёмкости и сроков реализации задач;
• Взаимодействие со сторонними разработками MS SharePoint на аутсорсинге;
• Организация и управление процессом разработки;
• Развивать и поддерживать клиентские и внутренние MS SharePoint порталы.

4) Какими проектами нужно заниматься: Проекты разработки портальных решений на базе Microsoft SharePoint. Внедрение систем аналитической отчётности.

5) Технические детали: Microsoft SharePoint Designer; SQL Server management Studio; SQL Reporting Services, Visual Studio;. Языки: C#, JavaScript, HTML, CSS, T-SQL. Платформы ASP.NET, WCF, SharePoint 2013/2016. Управление разработкой: JetBrains (YouTrack, TeamCity) / обсуждается.

Почему эта вакансия отстойная

В ней нет важного

Что важно для программистов? Я понятия не имею. Поэтому ищу информацию на эту тему.
За 5 минут нахожу исследование https://www.superjob.ru/research/articles/111451/vybiraya-rabotu-programmisty-ischut-interesnyh-zadach-bankovskie-operacionisty-perspektiv-rosta-rabochie-i-medsestry-horoshego-kompensacionnogo-paketa/.

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

  1. Высокая зарплата
  2. Интересные задачи
  3. Очевидные перспективы карьерного роста
  4. Удобное расположение офиса

Что из этого есть в вакансии? Ничего.

Нет ценника

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

Как бы хорошо ни была написана вакансия, если нет ценника, то 80% соискателей пройдет мимо.

Написано руководителем и техническим специалистом

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

Все длинные описания можно сократить до короткой фразы:

Требуется программист SharePoint 2013\2016 (серверная и клиентская разработка, C#, JS, WCF, навыки администрирования, T-SQL) для разработки порталов и систем аналитической отчётности.

Программисту SharePoint одна фраза будет так же понятна, как и длинное описание.

Не выделено ключевое

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

Неверная цель

Автор вакансии прокомментировал:

То, что указано в вакансии - написано в расчёте на широкую аудиторию, а не на 2-3 человек, написано так, чтобы можно было варьировать подход к кандидатам с разным опытом.

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

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

Как сделать хорошую вакансию

О компании и проектах

Не пишите «ведущая компания» - это вранье в 99% случаев. Даже если где-то есть рейтинг, где вашу компанию поставили на первое место, то соискателю на это насрать. Также соискателю насрать сколько там у вас лет опыта и в каких отраслях. Более того, вообще всем насрать на 20-летний опыт в нефтегазовой или любой другой сфере.

Напишите важное - какими проектами вы занимаетесь. Указывайте больше деталей. Детали продают.

Требуется программист SharePoint в ООО «Рога и копыта». Надо будет создавать портал и систему отчетности по исполнительской дисциплине. Клиент - нефтегазовая компания с 5 тысячами пользователей и 23 филиалами по всей России и странам СНГ. Придется взаимодействовать с аутсорсерами, контролировать качество их работы. А так же переписать модуль СЭД с SSOM на JSOM.

Требования к кандидатам

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

Надо разбираться в разработке и администрировании SharePoint 2013 и 2016, ASP.NET, WCF, уметь писать на JavaScript, C# и T-SQL. Обязательно знать jQuery и уметь делать рабочие процессы в SharePoint Designer.

Если важны личные качества, то не пишите банальности. Не надо писать про «ориентированность на результат», «умение работать в команде», «обязательность» и «исполнительность». Пишите только о том, что можете и будете проверять на собеседовании.

Условия работы

Пишите без брехни. «3 минуты от ТТК» - может оказаться так далеко от цивилизаии, что своим ходом туда не доберешься.
Обязательно укажите:

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

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

Укажите ценник

Это обязательно. Без этого программистская вакансия - не вакансия, а мусор. «Мы отталкиваемся от пожеланий кандидата» - вранье. Есть сумма, которую вы готовы платить, а на тысячу рублей больше - уже нет.

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

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

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

Заключение

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

  1. Что за компания и кого ищите
  2. Описание проекта, с деталями
  3. Требования, с акцентами на важном
  4. Условия работы
  5. Ценник
  6. Ключевые слова для поиска

Вот как я бы написал аналогичную вакансию:

ООО «Рога и копыта» (ссылка на сайт) занимается заказной разработкой программ. Нам требуется программист SharePoint на постоянную работу.

Надо будет создавать портал и систему отчетности по исполнительской дисциплине. Клиент - нефтегазовая компания с 5 тысячами пользователей и 23 филиалами по всей России и странам СНГ. Придется взаимодействовать с аутсорсерами, контролировать качество их работы. А так же переписать модуль СЭД с SSOM на JSOM.

Надо разбираться в разработке и администрировании SharePoint 2013 и 2016, ASP.NET, WCF, уметь писать на JavaScript, C# и T-SQL, HTML и CSS.
Обязательно знать jQuery и уметь делать рабочие процессы в SharePoint Designer.
Мы используем JetBrains YouTrack и TeamCity в разработке, их знание будет плюсом.

Условия работы
• Офис в 5 минутах ходьбы от метро Парк Культуры
• Команда из 6 программистов, двух аналитиков и одного тестировщика под началом руководителя проекта
• График работы с 10:00 до 19:00, можно удаленно по согласованию с РП
• В офисе всегда свежие фрукты

Зарплата белая, 120 000 рублей в месяц на руки. Есть проектные премии по окончанию проекта.

Условия обсуждаемы

Ключевые слова для поиска: SharePoint, SSOM, JSOM, ASP.NET, WCF, JavaScript, C#, T-SQL, HTML, CSS, jQuery

Текст вакансии должен продавать позицию кандидату и отсеивать тех, кто не подходит.

PS. Если с чем-то не согласны - пишите в комментариях. Кому понравилось - делайте перепост.



3 причины не верить почасовой ставке

За неделю ко мне обратились две компании, предлагали проект на SharePoint и спрашивали какая у нас (vnextsoft) почасовая ставка. Они не говорили какую конкретно задачу надо решать или какой портал сделать, их просто интересовала ставка.

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

1. Почасовая ставка не определяет стоимость проекта

Стоимость проекта - это произведение ставки на количество часов. Ставки варируются в 2-2,5 раза максимум. Количество часов, которое может быть потрачено на решение задачи, легко может отличаться в 3-5 раз. Один раз даже видел разницу в 10 раз.

Это вполне нормально. Алистер Коберн в статье “Магия числа ПИ для руководителей проектов” вывел простую зависимость - если команда новая и проект новый, то оценки нужно умножать на Пи в квадате, что примерно равно 9,87. Опытная команда, которая уже сделала аналогичные проекты, может сделать проект с трудозатратами в 10 раз меньше, чем неопытная. Кроме того, если у компании есть наработки, решающие задачи клиента, то оценка также может быть снижена.

Так что разница в оценках в 3-5 раз - вполне ожидаема. Почасовая ставка меньше влияет на стоимость проекта.

2. Почасовая ставка снижает качество

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

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

Компании, продающие “часы” сотрудников, пользуются формулой: стоимость часа для заказчика = ЗП в час * 3. Коэффициент 3 - это не жадность, а налоги + отпуск + оборудование + софт + управление + продажи + потенциальные простои + миниимальная прибыль, чтобы имело смысл заниматься бизнесом.

Если вам пытаются продать программиста SharePoint за 1500р\час, когда средняя ЗП - 120 000 в месяц, то этот программист увидел SharePoint в первый раз.

3. Почасовая ставка - это обман

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

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

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

Кто виноват Что делать

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

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



Встреча сообщества по SharePoint и Office 365

26 октября 2016 года состоится встреча сообщества по SharePoint и Office 365. Поделимся опытом реализации проектов на SharePoint и расскажем про новые возможности Office 365. Встреча пройдет в Microsoft Technology Center на Лесной. Начало встречи в 18:00.

В программе доклады:

PowerApps и Flow в Office 365
Михаил Бондаревский
В докладе покажу новые инструменты в Office 365 — PowerApps и Flow. Они станут доступны в ближайшем релизе Office 365. PowerApps — конструктор приложений мобильных приложений, который использует SharePoint Online как источник данных. Flow — конструктор рабочих процессов, ориентированный на конечных пользователей. 

Конфигурация Release Management в Team Foundation Server 2015 для решений фермы SharePoint 2013/2016
Александр Смотров
В докладе расскажу как автоматизировать сборку и развертывание решений для SharePoint. Как настроить автотесты для решений с помощью агентов Team Foundation Server.

Быстрая разработка и установка пакетов для SharePoint в облаке и на земле
Станислав Выщепан
В докладе расскажу про современные инструменты разработчика SharePoint, которые работают быстро, снижают количество ошибок и автоматизируют рутинные операции. Расскажу как создавать решения на TypeScript в vscode. Как загружать в SharePoint новые версии скриптов с помощью gulp. Как собрать.pnp пакет для установки и установить его в SharePoint Online и SharePoint 2016.

  Для участия обязательна регистрация, иначе вас не пустят в здание.

Если вы пропустили предыдущие встречи, то можете посмотреть записи:



SharePoint 2016 для архитекторов

Месяц назад SharePoint 2016 стал RTM. Это значит, что изменений в функционале SharePoint в ближайшие полгода мы не увидим.

SharePoint 2016 еще не GA (General Availability), то есть вы не сможете получить полноценный лицензионный ключ, только триал. Но уже пора думать о переходе на новую версию.

В SharePoint 2016 мало изменений с точки зрения пользователя или разработчика, зато много с точки зрения администратора и архитектора.

Подробнее рассмотрим новшества.

Project Server

Это первое о чем вы узнаете еще до установки SharePoint 2016. SharePoint и Project Server теперь одно целое. Ставятся они вместе, таблицы project хранятся в контентной базе SharePoint. Для включения Project Server 2016 достаточно одной команды PowerShell. С точки зрения маркетинга и продаж это все еще разные продукты.

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

Нет больше Foundation и не поддерживается SQL Express

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

У Microsoft была стратегия, что бесплатная версия Foundation должна продавать платную. WSS 2.0 даже включили в состав Windows Server 2003R2. Получилось ровно обратное - при наличии бесплатного Foundation заказчики даже не рассматривали платную версию.

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

SQL Express иногда использовали для разработческих\демонстрационных сред. Но теперь SQL Server Developer Edition бесплата для всех зарегистрированных разработчиков, поэтому потребность в Express-версии гораздо ниже.

Минимальные требования

Процессоров и памяти для SharePoint 2016 требуется столько же, сколько для 2013. Я бы рекомендовал иметь один сервер минимум с 16 гб оперативки и 4 ядрами для SharePoint+SQL для 300 активных пользователей, которые заходят на портал и что-то делают минимум раз в день. При росте количества пользователей масштабировать службы, которые не выдерживают нарузки.

Требования к софту изменились сильно - минимум Windows Server 2012R2 и SQL Server 2014 SP1, а лучше SQL Server 2016, чтобы поставить Reporting Services и PowerPivot. Минимальная поддерживаемая версия IE - 10, видимо потому, что используется CSS 3.

Нет больше Standalone режима установки

Еще со времен WSS 2.0 (может и раньше, я не в курсе) в SharePoint было два режима - Ферма и Standalone. Ферма могла быть развернута на нескольких серверах и требовала доменных учеток, а Standalone работал с локальными учетками и мог ставится даже без AD.

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

MinRole

Во время запуска Configuration Wizard спрашивают какя роль будет у сервера. Указав роль вы получете набор Service Application на этом сервере без возможности этот набор изменить. Кроме роли Custom, при которой вы сможете настроить службы на сервере самостоятельно.

С одной стороны это упрощает настройку. С другой - отказоустойчивая ферма теперь требует 8 серверов SharePoint (4 роли * 2 сервера), это в дополнение к двум серверам для баз данных и двум серверам для Office Online Server.

Мне кажется, что в реальности такое количество серверов никто поднимать не будет. Тем более на практике отказоустойчивую ферму можно собрать на 4 серверах вместо 8.

Распределенный кэш

В SharePoint 2013 была проблема. Он использовал AppFabric Cache 1.0, который содержал утечки памяти. Надо было руками патчить его до последнего Cumulative Update. В SharePoint 2016 теперь ставится AppFabric сразу с CU7.

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

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

На technet есть официальный гайд по настройке тайм-аутов, он акутален как для SharePoint 2013, так и для 2016. Но в 2016 появились еще несколько кэшей (ContainerType):

  • DistributedSharedWithUserCache
  • DistributedUnifiedGroupsCache
  • DistributedFileLockThrottlerCache
  • DistributedResourceTallyCache
  • DistributedHealthScoreCache

Для них тоже стоит увеличить тайм-ауты, особенно в случае односерверной фермы.

Site Masters и баг в личных сайтах

Для создания личных сайтов в SharePoint 2016 используется новый механизм, называемый Site Masters. Вместо создания новой сайт-коллекции и активирования фич с запуском кода, создается одна скрытая сайт-коллекция (master), а из нее новые коллекции получаются просто копированием на уровне базы данных. Можно самостоятельно добавить мастеры для шаблонов сайтов, если надо будет массово создавать коллекции по этим шаблонам.

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

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

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

Подробное описание бага - https://thesharepointfarm.com/2016/03/unable-to-provision-social-features-in-sharepoint-server-2016/.

Нет больше FIM в SharePoint

User Profile Sync Service, который по сути FIM Sync Service, появился в SharePoint 2010 и … не работал. Потом вышел CU, который его чинит, а следущий CU сновал ломал UPS. В SharePoint 2013 UPS стал работать стабильнее, но все равно было сложности с настройкой и отладкой.

В SharePoint 2016 окончательно решили этот вопрос - выпилили FIM из SharePoint. Теперь для простых сценариев есть AD Import, а для сложных можно отдельно установить Microsoft Identity Manager (MIM, теперь FIM так называется) и настроить синхронизацию в нем. Microsoft подготовил скрипты для настройки MIM - https://github.com/OfficeDev/PnP-Tools/tree/master/Solutions/UserProfile.MIMSync.

С точки зрения лицензирования MIM Sync Engine требует только Windows Server CAL, поэтому не увеличивает лицензионную нагрузку.

Продолжение следует

В следующий раз я расскажу про Office Online Server, Excel Service и PowerPivot.
Кто хочет научится устанавливать и настраивать все возможности SharePoint - приходите на тренинг.
Описание и регистрация по ссылке https://gandjustas.timepad.ru/event/317082/.