пятница, 3 марта 2017 г.

Как начать планирование релиза?

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

"Выпуск релиза каждые полгода" и все такое. У этой модели много разных названий, а сама модель работы очень надежная и эффективная. Вот только на каждые полгода ощущается "трение": один релиз уже выпущен, а работа на цели следующего релиза все не начинается и не начинается... Как же так?

Имхо, вполне нормальная ситуация: всегда есть недоделки. Количество недоделок на конкретную дату зависит от "качества" работы в предыдущие полгода. Наделали много долгов - будет много недоделок. Наваяли код, обложили тестами, сделали документацию, наклепали примеров, подготовили презентации, провели тестирование всего этого на "тестовых клиентах", внесли исправления по выявленным проблемам - и долгов будет мало. Трение на старте нового релиза зависит только от этого.
С увеличением размера продукта такое трение становится более разнообразным: 10 человек наделали разное количество долгов и кто-то сидит допоздна каждый день, а кто-то дергает за рукав со словами "ну когда уже релиз планировать будем?" Такая ситуация тоже вполне нормальна и нет смысла откладывать работу только для того, что бы "начать работать над новым релизом одновременно" и именно такой подход мне кажется наилучшим.
Это отличный вариант, но с ним вполне можно "бежать впереди паровоза" и действовать неадекватно "мировой ситуации":
  • В целом по команде не должно быть явных перекосов по долгам, когда у кого-то пусто, а у кого-то полные штаны этих долгов.
  • Установленные критерии качества соблюдаются (ошибки быстро исправляются, вопросы быстро отвечаются).
  • В целом по продукту усилия должны быть приложены по направлениям, которые все признают важными (цели на год-два).

Поэтому я же таким энтузиастам начинаю "вставлять палки в колеса" в соответствии с этими пунктами:
  • "У тебя баги кончились? Фиксить нечего? Вопросы по твоим фичам не задают?"
  • Почему бы тебе вместо нового кода не помочь поправить известные ошибки в новом коде фичи Х? Ах не ты делал... А какая разница? Все равно эти ошибки придется исправлять и чем раньше начнем, тем быстрее получим хорошее качество. Перераспределим ресурсы адекватно реальности.
  • Почему бы тебе вместо твоей идеи "а давайте сделаем Х!" не заняться моей идеей "сделать У"?
  • Вот у нас трафик вопросов большой и специалисты поддержки почти по ночам уже сидят - помоги им раз уж закончил со своей работой по выпущенному релизу. Посмотри почему у них такой завал и как улучшить ситуацию?
К счастью энтузиастов, у меня количество таких палок весьма ограничено и можно заранее подготовиться к попыткам "вставлять их в колеса" и начать таки работать на новый релиз:
  • Да кончились. Да, нет багов. И вопросов тоже нет.
  • Либо фичам готова к выпуску в релизе, либо нет. В новом релизе могу помогать, а сейчас лучше выпилить сырую фичу из релиза.
  • Вон опрос провели и выходит, что нафиг не нужен твой "У", все голосовали за мой "Х". И вопросы я еще посмотрел - то же самое выходит, список вопросов в приложении 1.
  • Вот кто выпустил то, из-за чего специалисты сидят - тот пусть и помогает. Опять же премиями можно мотивировать. А я прошлом релизе начал и закончил так, что никто нигде не засиживается. И могу еще что-нибудь сделать с таким же результатом.
Если есть понятные ответы на эти вопросы, то нет причин откладывать работу. Можно "прям щас" составить план на себя в новом релизе и сразу же начать по нему работать.

"Unit тесты" или "Функциональные тесты"

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

Например, тест из первой группы мог бы проверять результат работы метода, который должен посчитать новое значение в зависимости от переданного значения масштабирования экрана ("Make texts larger" в Windows для HighDpi мониторов): передали в него исходную цифру и несколько масштабов - проверили цифру под каждый масштаб.

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

Что же мне выбрать для эффективной работы?

Зачем автор вписал тут буквы "protected virtual" ?

public partial class MyForm : Form {
  private MyForm() {
   protected virtual void Setup(string caption) {
    ...
  }
  public static void ShowMessage(string caption) {
    MyForm form = new MyForm();
    form.Setup(caption);
    form.ShowDialog();
  }

Зачем автор вписал тут буквы "virtual" ? Ведь этот метод вызывается только из статического метода и никакие "override" в это место не добавить.

Одноглазые тесты

Возникла у меня в приложении проблемка: при смене фильтра в моем гриде пропадало "выделение" строки, т.е. строка есть, ее видно, но она просто не "выделена". А выделение строки очень важно: кнопки Delete/Print и многие другие работают с выделенными записями, т.е. нет выделенных записей - кнопки недоступны.
И в результате поведение моего приложения выглядело ужасно: сменил пользователь фильтр, видит в гриде нужную запись, а удалить ее не может, потому что кнопка Delete недоступна. Кто виноват? Конечно же программист!

Я для этого сценария сделал костылик и написал тест с проверкой выделенных записей в этом сценарии:

среда, 6 июля 2016 г.

Как сравнить свой продукт с конкурентами?

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

Если исходить из этого, то конкурируем не мы, разработчики компонент, а разработчики приложений. Мы для "своих" разработчиков всего лишь предоставляем хорошие тулзы, что бы они быстро сделали впечатляющие прототипы и на прототипах прояснили все важные вопросы заказчиков. Если "наши" разработчики уже отстают от ХХХ (например https://blogs.msdn.microsoft.com/visualstudio/2016/06/28/webinar-build-cross-platform-apps-with-visual-studio-and-xamarin/ или https://blogs.msdn.microsoft.com/visualstudio/2016/06/16/apache-cordova-the-browser-based-workflow/), то можно конечно повыбирать и посравнивать, но эти "свои" уже начали думать "а не перейти ли на другие языки и технологии? как-то там уже все очень просто получается по презентациям, а то я хорошо знаю и умею винформс но все равно не получаю заказы из-за требования iOS/Android/clouds".

И если исходить из этого, то один только "рич" или один только "чарт контрол" или даже один только "грид" картину не меняет, все равно в приложении нужны риббон, навбар, tabbedmdi, разнообразные редакторы и их надо либо делать самому либо искать готовые. А приложение должно работать на iOS, Android, Win и надо много чего-то делать для этого. Да и само приложение должно работать без наличия собственных hardware серверов, на маленьких смартфонах или ноутах с данными в clouds/azure/xxx.

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

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

среда, 20 января 2016 г.

Юнит тесты...

В своем проекте я некоторое время назад использовал сторонний компонент XComboBox и наполнил его список доступных элементов вот таким образом:

            foreach(object obj in list) {
                comboBox.Items.Add(obj.Name);
            }

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

            foreach(object obj in list) {
                comboBox.Items.Add(HttpUtility.HtmlEncode(obj.Name));
            }

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

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

понедельник, 14 декабря 2015 г.

Оптимальное распределение ресурсов команды по задачам продукта

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

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

На одинаковых требованиях каждой области продукта это отлично работает. Внутри одной области работает еще лучше. Однако если требования различны, то перескакивание с одной области на другую может быть дорогим, ведь опыт и знания не появляются мгновенно. Возникают задержки на "в первый раз вижу", "а я и не знал" и банальное "вспомнить что я тут вообще делал в прошлый раз три года назад". Эти задержки "съедят" нужное им время и потом конечно же исчезнут, а разработчик наладит адекватную скорость работы. По моему опыту, это примерно полгода-год. Но потом с ним снова случается планирование и приходят новые Самые Важные Задачи, происходит новый скачок в соседнюю область и задержки возвращаются. На протяжении в три года или больше этот подход может стать катастрофическим для продукта: каждая его область начинает отставать от ситуации в мире, от конкурентов, от ожиданий клиентов и других факторов меняющегося окружения. Происходит осознанная и неосознанная компенсация скорости работы за счет качества результатов. А компания получает не очень-то веселый изменение: источник доходов был, а потом "сам собой" слился.

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

Из вариантов остается промежуточный: убегать с одной области продукта в другую можно, но очень редко (время эффективной работы должно быть существенно больше времени на обучение нового сотрудника). И развитие каждой области должно быть постоянно поддержано ресурсами, достаточными для того, что бы эта область соответствовала изменениям в мире (с критерием результативности "действительно соответствует")..

Однако и этот вариант можно назвать неэфективным из-за постоянной поддержки на развитие каждой области: задачи в ней совсем не Самые Важные, однако ими постоянно кто-то занимается. Это широкий простор для амбициозного руководителя: "Я нашел где мы можем здорово сэкономить! Ура мне и премию!" Или для бюрократа "По принятой методологии должен быть список задач и все должны их делать в порядке приоритета! Я наладил такую работу, ура мне и премию!" Эффект от такого изменения заметен сразу: Самые Важные Задачи кто-то сразу начинает делать! Они уже не ждут своей очереди! Они уже в списке "Doing"! Премии получены, все воодушевлены и с уверенностью смотрят в будущее.

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

Вот такой невеселый конец.