Если нельзя, но очень хочется, то нужно обязательно и ничего в мире не стоит того, чтобы делать из этого проблему!


Интересна Java? Кликай по ссылке и изучай!
Если тебе полезно что-то из того, чем я делюсь в своем блоге - можешь поделиться своими деньгами со мной.
с пожеланием
столько времени читатели провели на блоге - 
сейчас онлайн - 

суббота, 23 февраля 2013 г.

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

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


Самое главное в поэтапном how to, первый шаг которого (не самый простой), начинается с раскатывания шариков разной величины.


Очень рекомендую для деток, а особенно для их родителей сенсориков :)

Как подбирать музыку в MIDI?

Сегодня с утра, некто FLASH_3 постучался в скайп: "ВИДЕЛ ВАШИ РАЗБОРЫ ПЕСЕН НА ФОРТОПИАНО. БОЛЬШОЕ СПАСИБО." Пожалуйста, но это не основная моя деятельность - просто время от времени брынчу себе что-то, а чтобы хорошо разучить - подбираю вначале сам. И тут же мне предложили подобрать "Fly - Ludovico Einaudi".


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

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

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

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

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

Звук обычно рспостраняется в mp3 - там можно записать что-угодно (лишь бы звучало). Но в MIDI записываеются только инструменты: какой инструмент, что играет, как громко, что с эхом и так далее... Вот пример midi композиции легендарного и бесконечного Фредди Меркьюри и его группы Queen "Who wants to live forever". Открой его в любом проигрывателе. Послушай. Скорее всего звук будет ужасный. Дело в том, что так его воспроизводит тот примитивный MIDI синтезатор, что встроен в твой компьютер. На более качественном оборудовании он будет звучать лучше. Но не в этом фишка midi - а фишка в том, что там записаны все ноты всех инструментов. Взгляни на размер файла. 20828 bytes - это в 100 раз меньше, чем та же песня в mp3 (пример минусовки). Звук отличается - просто сравнивать нечего. Но напомню, что в mp3 все записано как есть - смешанный звук, а в MIDI записаны ноты инструментов причем раздельно. В любой момент времени в MIDI я могу зменить скрипку на фортепиано или гитару и это делается почти щелчком пальцев (конечно же с помощью программы, о которой позже).

Итак нам нужен MIDI. Это самое первое что я буду делать. Гуглим "название песни + MIDI". Обычно MIDI выкладывают в ютьюбовских роликах-разборках композиции: либо в description к ролику от Автора либо уже в комментах участников.


Чаще, конечно, Автор не выкладывает ничего, тогда надежда на комментарии... Так же в комментариях можно найти ноты (sheets) их тоже неплохо бы себе скачать (на случай, если MIDI не найти а уроков нет, нам прийдется работать с нотами)


Так, я перелопачиваю 10-30 видеороликов, других сайтов в поисках хоть чего-нибудь (MIDI, видеоуроки, ноты) и параллельно прислушиваюсь к той версии исполнения, которая мне больше всего нравится. дело в том, что каждй играет по-своему. Принципиально не выбираю простые исполнения (которые для моего уровня были бы в самый раз), потому как оно и звучит никак, а значит не будет меня вдохновлять во время подбора/разучивания, и так же не будет настоящим челлендежем для меня.

С композицией "Fly - Ludovico Einaudi" мне повезло. Удалось найти и MIDI и ноты.

MIDI я немного подправил, потому как были очепятки, которые резали слух. Но даже после исправления все-равно есть чувство, что оно надо переделать.

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


Итак, слава Гуглу, мы нашли материала достаточно. Нслушались, насмотрелись. Быть может даже midi нашли! Теперь нам надо установить программу в которой можно редактировать MIDI. Я пользуюсь Fl Studio. Ее можно легко найти с помощью того же google.
Программа достаточно сложная для новичка, потому есть ряд уловок, ускорябщих работу в ней. Для начала мы не будем настраивать проект с нуля, а откроем в программе любую MIDI, перетаскивая файлик прямо в окно программы. На вопрос о загружке отвечаем "Accept"



После на панели инструментов жмем



И видим что-то вроде



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



Сверху есть ползунок прокрутки горизонтальный - можно поскролить



Сейчас стоит нажать Ctrl-A, а потом Delete - все удалится. Теперь мы имеем чистый лист, который можно Save as в другой файл. Так мы сделали для того, чтобы не настраивать ничего. Потому как если сделать File - New то там надо много сделать/настроить чтобы все зазвучало как MIDI. Лишняя, сложная работа. Если же у нас есть готовый MIDI который мы хотим подредактировать - тогда удалять ничего ненадо.

Но допустим (для полноты эксперимента) у нас MIDI нет... Стоит разобраться с тем, как тут создается музыка.

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



Создать нотку можно левой клавишей мыши, а правой стереть. При этом маркер должен быть выбран такой (карандашик)


Проиграть то, что получилось можно нажав клавишу Пробел.

Выделить часть ноток можно мышкой, удерживая Ctrl (выделить с нуля) или Ctrl-Shift (добавить к выделенному). После можно перемещать группу, схватившись мышкой за одну из выделенных ноток, либо удалить, нажав Delete. Если же нажать и подержать левую клавишу мыши на одной из выделенных ноток, то создастся копия всей выделенной группы (copy - paste). Смотри видео.


Разберемся с дольками (длительностью) нот.



Если вдруг у тебя полосок между тактами не так как у меня, тогда отправляю тебя в меню



Вообще там лучше поставить step (или 1/16 - этого хватит с головой)

Рисование нот не хитрое занятие в FL Studio. Для начала надо кликнуть на существующую нотку, длительность которой мы хотим получить, а потом кликнуть в друго месте. Так же получившуюся нотку можно увеличить или уменьшить. Если вдруг сетка нам мешает, то можно с Alt изменить размер нотки более точно (не рекомендую). Так же с Alt можно ее перемещать боле точно (опять же не рекомендую игнорить сетку, а выставить ее на 1/16 - step).


А теперь попробуем по нотам назвучать вот это в FlStudio


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


(1) - то, как быстро играется композиция. Тут указано, сколько четвертых (1/4) долек в минуту прозвучит. Если это число поделить на 4, то получим количество тактов в минуту. В нашем случае - это почти 30. То есть каждый такт длится 2 секунды.

(2) - указывает на размерность (метр). Верхняя цифра говорит о том, сколько, а нижняя - каких нот, умещается в такте

(3) - это 1 такт. Он разделен вертикальными (тактовыми) чертами. В него вмещается четыре четвертых (1/4) ноты, восемь восьмых (1/8), одна целая, две половинки... Нагляднее продемонстрирует вот этот урок.

(4) - а это 4 восьмых ноты. Восьмые рисуются с хвостиком, если они одинокие, либо сеодиняются вместе в группы "крышками", как тут.

(5) - целые ноты (при размере 4/4 они звучат весь такт), залигованы с такими же нотами в соседнем такте, что значит - они звучать будут сичтно все два такта.

(6) - указывает на тональность. Если нотка попадает в эту линеечку, значит берется диез (следующая черная, на пол тона выше). И так для этих же нот всех октав - если до-диез то он везде диез. Самая сложная как по мне часть :) Хорошо, когда все До-мажор (все клавиши белые).

В целом, должно быть ничего непонятно :). А потому отправляю почитать мат-часть тут. А вот интересные интерактивные уроки с http://corpuscul.net. После должно стать понятно.

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

После этого я могу воспользоваться другой программой - Synthesia, чтобы визуализировать игру.

четверг, 21 февраля 2013 г.

Вышла новая Snake Coding Dojo

Ура! Теперь у нас с Серегой 3 dojo фреймворка. Только что выкатили Snake Coding Dojo



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

Пока в ней только один единственный уровень. Но в мыслях есть исправить это.

Управление такое же как в тетрисе. Детали тут...

Как запустить сервак у себя на локали читаем тут... Но хочу предупредить - намного интереснее играть не в одиночку, а в группах. Dojo все-таки...

Игра распостраняется бесплатно и ты можешь использовать ее для своих целей. Но вместе с этим мы хотим получать фидбек от тебя (а так же от участников) после очередной игры. Фидбек любой участник может оставить тут (http://bit.ly/snake-dojo-feedback). За фидбек, спасибо большое!

Исходники, лежат рядом с тетрисом, на GitHub.
Вот сервак для ленивых, а вот клиент (пока только java).

Айда к нам в группу на Facebook!

Как фильтровать svn repo с history

Задача такая - раньше я коммитил все свои Java for fun проекты в отдельный репозиторий. Теперь я хочу, чтобы только один из этих проектов (но со всей историей) остался в результирующем репозитории. Как это сделать? Стал гуглить....

Для начала скажу, что у меня стоит (кроме всего прочего) TortoiseSVN и им был создан репозиторий. Я попробовал установить svnserve и попытался сделать дамп исходного репозитория. На это получил ошибку.
C:\>svnadmin dump D:\JavaForFun\_Repo > all-dump
svnadmin: Expected FS format '2'; found format '4'
В сети говорят - попробуй последнююверсию. Оки! Попробовал то же самое сделать из папки bin установленного VisualSVN Server (вот очень хороший гид, по поторому можно установить себе сервер по вкусу).
Я потоврил команду и на этот раз все получилось.
C:\Program Files (x86)\VisualSVN Server\bin>svnadmin dump D:\JavaForFun\_Repo > all-dump
* Dumped revision 1.
* Dumped revision 2.
* Dumped revision 3.
* Dumped revision 4.
* Dumped revision 5.
* Dumped revision 6.
Спасибо! В результате образовался в папке текстовый файлик all-dump.
В след за этим я воспользовался командой
svndumpfilter include Snake < all-dump > snake-dump
Что отфильтровала в новый дамп с именем snake-dump только те ревизии, которые содержат Snake. Супер! Осталось только поднять новый репозиторий
svnadmin load --ignore-uuid D:\snake < snake-dump
И вот результат ...
 А вот как выглядят исключенные ревизии..
Дальше я перегнал все хистори в git, который потом залил на git hub. Но это уже другая история...

вторник, 19 февраля 2013 г.

TDD тренинг из угла комнаты

Начну с термина "Training from the back of the room". С ним мы с Сергеем познакомились в прошлом году. До этого наши тренинги были больше похожими на семинары (пример такого семинара в КПИ), на которых мы рассказывали ребятам, что такое ТДД, давали практическое задание и помогали с его реализацией на новом инструменте. 

Мы много говорили и, как позже стало нам понятно - тренинг это не семинар. Это на семинаре/вебинаре можно говорить, а на тренинге стоит поднимать тяжести и делать это практически все время, отведенное под тренинг. Опытные тренера (Максим Роменский и Ирина Синчалова) в разное время говорили нам, что тренинг - это 70% работы и всего 30% разговоров... И именно в этом порядке, не иначе (об этом уже нам поведал Слава Панкратов, рассказывая про цикл Колба на одном из своих мастерклассов). 

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

Стоит менять подход. И тут у нас в руках появляется инструмент Coding Dojo. Его привозит к нам Johannes Brodwall. В тот день Сергею удалось покодить с Johannes в паре решая задачку Primes Factor. Кроме интересной Primes Factor мы получили на руки инструмент Coding Dojo и так же провели его в GlobalLogic. Это был успех! О нем свидетельствовали 100% позитивный фидбек участников. Собака зарыта тут! И мы стали копать. Вернее разрабатывать...

Наши Automated Testing Dojo для автоматизаторов-тестироващиков (спасибо Мише Полярушу и Андрею Дзыне за поддержку, а так же Глебу Рыбалко и  Вике Мусияченко за предложение "а придумайте чего-нибудь для автоматизаторов на конфу"), а потом и Tetris Coding Dojo для программистов, доказали нам что мы роем в правильном направлении.

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

В ходе проведения dojo с Сергеем мы были как бы "в углу команты", наблюдая за тренингом который по факту шел сам. Будучи при этом на подхвате, чтобы в любой момент дать ответ на вопрос участников. А еще лучше переадресовать вопрос остальным участникам. И никакой критики! Эксперимент однозначно приветствуется, когда видишь очки игроков на доске и свое место в leader booard. Попробовал свое -> посмотрел, как оно -> если не ок -> попробовал новое -> посмотрел, как оно -> принял решение оставлять либо дальше экспериментировать... Колб был бы доволен...


Но это касается развлекательных мероприятий. Тренинг же, особенно, когда ребята платят за него деньги, требует более детальной проработки. Кроме того фидбеки предыдущих тренингов говорят о том, что стоит изменить. Да и новый опыт в Dojo говорит о том же. Так получается, что наш новый тренинг практически никогда не похож на предыдущий - всегда что-то новое, всегда более эффективное (ибо проверено).


Так было и в этот раз. Мы с Сергеем полностью переделали наш тренинг с нуля. Включили в него только то, что необходимо и исключили из него все лишнее. И на этот раз у нас вот что получилось: 
- мы говорили мало (в пределах 30%), 
- ребятам было чем занять свой мозг (мы выбрали лучшие игрушки, в которые за год игрались сами), 
- ребятам это было полезно, поскольку основная тема - тренинг TDD под присмотром коучей.
- это было эволюционно - юнит тестирование -> TDD + Test List -> TDD в legacy -> TDD и Refactoring -> TDD и SOLID (SRP, OCP, (IoC) DIP) -> Unit Testing с Mock.

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

Тренинг начался с разогрева. Ибо рано утром все мы очень инертны, чтобы сразу думать. Сергеем понравилcя инструмент "Миф-Реальность". Суть его вкратце в том что есть карточки, на них написано некое утверждение. И вот заходит первый участник, открывает свой ноут (почту проверить), а мы ему даем карточки и просим разложить что по его мнению миф, а что реальность. Следующий участник тренинга приходит и видит, как уже что-то происходит и тут же включается. Это нам пообещали наши тренера, и так оно оказалось на практике. Не занятое проблемой сознание скучает и ищет себе развлечения. Мы имели с этим немало хлопот на первых своих тренингах. Сейчас же знаем - начинать стоит с включения лампочки в голове. Задание "Миф-реальность" очень хорошо для этого подходит. Вот примеры утверждений, написанных на карточках. 
  • На написание тестов уходит слишком много времени   
  • Тесты отвлекают от размышлений над логикой
  • Все и так работает   
  • Тестировать слишком сложно
  • Заказчик никогда не согласится на полноценное ТДД в команде   
  • Рефакторить без тестов опасно
  • Код меняется редко   
  • В ТДД можно использовать дебаггер
  • С ТДД приходится больше общаться в команде   
  • С ТДД овертаймишь больше
  • С ТДД нет ручного тестирования   
  • Тесты не придется переписывать
  • ТДД позволяет получить мгновенный фидбек от системы   
  • ТДД приводит к 100% степени покрытию кода тестами
  • ТДД избавит нас от всех проблем   
  • С ТДД не надо проектировать архитектуру
А по результатам (голосование) можно судить о настроении группы касательно предложенной темы. Конечно же этого недостаточно, а потому мы опросили ребят еще до начала тренинга. Нас интересовал существующий опыт ребят и их вопросы. Это позволило нам оттюнить тренинг под ребят, а вопросы мы выписали на флипчарт и позже, в конце дня возвращались к нему. Это был наш тестлист.... 
  • Как эффективно использовать TDD, чтобы не тормозилась разработка? Какие выгоды даст TDD?
  • Как работать в парном программировании, не мешая?
  • Как правильно выбирать инструменты тестирования в зависимости от решаемой проблемы: EasyMock, PowerMock, Mokito ... ?
  • Необходимо ли использовать TDD во всех случаях проектирования/кодирования?
  • Насколько TDD повышает качество кода?
  • Реально ли использовать TDD с незнакомым фреймворком/чужим кодом?
  • С чего начать?
  • В каких случаях лучше использовать TDD, а в каких его использование нецелесообразно?"
  • Есть ли смысл покрывать тестами незнакомую логику на начальном этапе расширения функционала проекта?
  • Как сделать, чтобы рефакторинг кода требовал минимальное изменения кода тестов?
  • Есть ли смысл в UNIT-тестах для делегирующего функционала? 
  • Как писать тесты для легаси кода?
  • Как тестить класс, нарушающий Single Responsibility Principle?
А опрсник перед тренингом были такой:
  • Пробовал ли использовать TDD в реальных проектах? (опиши пару предложений как это было, что не получалось, какие вопросы остались открытыми)
  • Какие вопросы ты хотел бы нам задать? (чем больше - тем лучше)
  • Зачем тебе этот тренинг? (как узнал про тренинг, что будешь делать после него, ... )
Чем понравилась группа, так это тем, что ребята хотели понять - зачем им TDD, как он им может пригодится для решения каждодневных задач. Это чувствовалось на протяжении всего тренинга. Ребята пришли за знаияниями. И нет ничего лучше для тренера. Я помню вечера обоих дней тренинга - я шел домой пешком, любовался видами вокруг - у меня в голове не было ни одной мысли, все вычистили за день :) Домой я пришел, душ, сёрбнул поесть,  свалился с ног на диван и тут же заснул. Усталость может быть приятной.

А утром в 6:00 как штык править тренинг, ведь первый день внес свои коррективы. И с удовольствием. Потому что не зря идешь...

Что-то отвлекся я. Итак у нас первый день тренинга 10:15. Ребята в сборе. Мы познакомились. За "миф-реальность" проголосовали, вопросы выписали и второе задание в студию! Игра FizzBuzz (спасибо Диме Миндре). Мы на тренинге для тренеров с Сергеем играли в похожую игру - 33 называется. Правила простые. Играют стоя. Говорят по очереди число от 1 до 33. Если твое число делится на 3 либо содержит 3ку ты должен хлопнуть в ладоши, иначе сказать число. Ребята обычно сбиваются и тот кто налажал - должен начать с начала. Весело. Вот и мы решили ее повторить, но в несколько усложненной форме, называемой FizzBuzz.

Итак групповая игра. Счет начинается с 1. Каждый следующий по кругу участник работает с числом на 1 больше, чем у коллеги: он говорит «физ» если его число делится на 3 без остатка, говорит «баз» если его число делится на 5, говорит «физбаз» если его число делится и на 3 и на 5 одновременно, либо говорит само число.
Если кто-то из участников сбивается, то он начинает игру с начала. Игра окончена, если команда дошла до 33 не сбиваясь со счета.

К реализации. А теперь найдите напарника и напишите вместе по Test Driven Development метод, который подскажет вам, что надо сказать в тот или иной момент. Используйте TDD так, как вы умеете. Вот сигнатура метода: 

Template рабочего проекта можно получить на общем svn repo, которое мы подняли на одном из наших ноутов. Это очень удобно, поскольку в любой момент времени мы как тренера могли иметь доступ к исходному коду любой пары, вносить в него изменения, изучать. Так же ко всему коду имели доступ и другие ребята, и хоть мы условно разделили репозиторий на 6 одинаковых папок (для каждой пары), это не помешало нам всем перемиксовать пары на второй день.


В качестве репозитория был выбран VisualSVN Server из за своей простоты. Поднялся на раз два. Это было удобнее, чем все наши предыдущие попытки. С самого начала дня IP компа с полным путем к реппозиторию был выписан на флипчарте. Ребятам сообщили, что там они могут скачать проект своей пары. Номер пары был написан на стике, который был приклеен к столу. Так и мы и пара знала какой у нее номер. 

Кстати да - вся работа проводилась все два дня в парах. Мы параллельно с ТДД рассматривали (да нет же - трейнились) правила игры в pair programming. Было много откровений, так же и у нас. Например лично для меня было новостью, когда ребята работали за двумя ноутами но в паре, просто ноуты очень разные все и сложно привыкнуть к разным калвиатурам. А тут вначале ты смотришь в мой ноут, а потом я в твой - SVN репозиторий жеж один. Супер! люблю уносить из тренинга что-то новое для себя.. 

Про парное программирование мы сказали (вернее написали на раздатках) всего ничего. Что есть две роли. Говорит тот, у кого клавиатура – пилот – он рассказывает то, что сейчас реализует. Напарник – штурман – не критикует, а следит за «очепятками» пилота. Клавиатурой (и ролями) меняются, когда текущий шаг сделан, либо когда пилот «сдается» (не может решить текущий шаг за 5 минут). 

В процессе сегодняшнего дня мы еще неоднократно цепляли тему правил парного программирования - что должен, а что не должен делать человек находящийся в той или иной роли. Например пилот не должен отвлекаться, но если он отвлекся, то шутрман должен выписать его идею в тестлист. Вторую роль весь день называли "хранителем тестлиста", а вопрос "где ваш тестлист" наверное прозвучал из наших уст раз 30 не меньше. Вначале мы с Сергеем боролись с привычкой ребят все держать в голове, но что порадовало, так это то, что на следующее утро ребята уже сами вели тестлисты к своим заданиям и мы на это больше не отвлекались...Супер! Цель тренинга развить новые привычки, и похоже с test list это получилось.


Test list сам по себе полезный инструмент. Просто очень удобно не держать все в голове, а в парном программировании штурмана надо было как-то еще нагрузить - не только же ошибки искать будет. Вот и стал он хранителем тестлиста. И цель его не болтать, а записывать. Болтать он вообще не должен ничего, даже если он Senior по сравнению с нубчиком пилотом. Да он знает, что так писать нельзя, но пока он штурман, он должен дать возможность пилоту закрешиться. Только получив больно граблями по голове пилот отдает клавиатуру и внимательно начинает слушать. Если же его перебить посреди его реализации, он скорее всего в мыслях продолжит кодить и слушать опытного не будет. 


Но тут штурман не должен давать много свободы пилоту. Еще одна его роль - следить за временем на реализацию текущего теста из тест листа. 5-10-15 минут не больше. После этого времени штурман должен настоять на том, чтобы пилот признал неудачу и отдал ему клавиатуру. Штурман - хронограф пары, он следит з временем.... 

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

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

Идея "High five" доработана идеей Сергея раздавать монетки-шоколадки за каждый такой хлопок ладошками. А раздавать было что.


Всякий раз, когда вы получаете зеленую полосу, «дайте пять» своему напарнику – вы только что продвинулись чуть ближе к финишу – это стоит отметить. Каждый ваш «high five» мы будем  поощрять шоколадными медалями

Но раздавать конфетки-монетки было так приятно, что мы стали их раздавать за хорошие вопросы, когда слышали в диалоге пары правильные с точки зрения ТДД мысли.... Конфетки расходились очень быстро. Кто-то их ел. Кто-то собирал. В любом случае конфет после тренинга осталось и моя дочь передала "больше спасибо дядям, которые не съели все ее конфеты"

Решение задачи FizzBuzz было не сложным. Но мы хотели, чтобы ребята попробовали реализовать его по TDD как умеют, так как они его (TDD) понимают. И стало понятно - перед нами группа подготовленная, как минимум юнит тестирование регулярно используют. И это замечательно! А решение было где-то таким:

package com.codenjoy.tdd;
import static junit.framework.Assert.assertEquals;
public class FizzBuzzSolver {
    public static final String FIZZ = "fizz";
    public static final String BUZZ = "buzz";

    public static String get(int num) {
        validate(num);
        String result = null;

        if (num % 3 == 0 && num % 5 == 0) {
            result = FIZZ +"&"+ BUZZ;
        } else if (num % 3 == 0) {
            result = FIZZ;
        } else if (num % 5 == 0) {
            result = BUZZ;
        } else {
            result = String.valueOf(num);
        }
        return result;
    }

    private static void validate(int num) {
        if (num<1 || num>33) {
            throw new IllegalArgumentException("Argument should be in [1-33].");
        }
    }
}
И валидация и выглядит симпотичненько. Но нас с Сергеем как тренеров интересовало не так решенное задание, как ответ на вопрос:
- как проходит работа в парах
- как ребята понимают TDD (а именно мантру Красный Зеленый Рефакторинг) 
- как проходит работа с тест листом

Второе задание было несколько сложнее, называлось оно PrimesFactor. Цель задания показать, каким простым должен быть каждый шаг. Мы даже в раздатке указали подсказки, но кажется туда никто не смотрел - ребятам было интересно все реализовать самим.

Пока ребята реализовывали задачу, мы с Сергеем как коршуны летали ожидая вопросы в нашу сторону. Мы во время подготовки договорились, что будем стараться молчать так долго, сколько это будет возможным - говорить только, если нас спросят (особенно это больше касалось меня ☺).

Под конец этой игры мы с Сергеем записали свою реализацию, чтобы продемонстрировать ребятам, как это происходит, когда "рука набита". Дело в том, что ТДД практики обещают ускорение разработки, и это понятно - как минимум, в ТДД исключен самый трудоемкий процесс разработки - отладка. Но из-за тяжеловесности дисциплины ТДД поначалу время на разработку простых кейсов может достигать 5x, что неприемлемо. Чтобы не остался неприятный фидбек "что это долго" мы показали ребятам это 8-минутное видео...


Итого что имеем? Привычки ломать сложно, коуча в команде нет (а в XP предусмотрен персональный коуч, как в SCRUM предусмотрен ScrumMaster), прироста производительности не наблюдается.... Поводов спрыгнуть с ТДД очень много, да и этот Legacy проект, который еще непонятно как протестировать.... В общем, ТДД хорошо бы изучать еще в вузе, вместе с программированием...


Я лично спрыгивал три раза за пол года, пока не пришла привычка и я не стал видеть прирост эффективности. У Сергея становление ТДД случилось быстрее на пару месяцев. Сейчас же мы можем использовать как ТДД так и классику со своим DEBUG, и выбираем в зависимости от случая. Иногда и подебажить быстрее - а значит не грех. ТДД всего лишь инструмент, который где-то хорош, где-то не очень. Об этом мы и говорили все два дня. Цель тренинга как раз получить новый инструмент в свой арсенал разработчика, или даже не так - как можно больше времени провести с инструментом под присмотром опытных (слава Богу) коучей. А потом попробовать еще раз самостоятельно. Вообще идеально, если на своем проекте комнада будет иметь коуча 40 часов в неделю. Но такого числа специалистов практикующих ТДД достаточно, чтобы отвечать на хитрые вопросы команды и убеждать через парное программирование на самом деле не так уж и много.... А жаль...


Итак первая половина подошла к концу. И мы все вместе мигрировали в общепит.


Покормили нас вкусно и за счет тренинга. После обеда мы минут двадцать ничегонеделали :) Но потом начался Tetris coding dojo, но не обычный как мы в него неконтролируемо играем на соревнованиях среди проггеров. Сейчас мы вооружившись тестлистами и ТДД стали писать непривычно. 

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

Так первый день подошел к своему концу. Мы обсудили вопросы, которые выписали с утра



И отправились по домам.

Второй день был достаточно хардкорным. Заданий было всего три, но какие. Первое задание - LegacyCaclulator. Это один класс, который умеет суммировать x-ричные числа. Он запутанный. Он без тестов. Он ужасен. Задача - реализовать на его основе сумматор римских чисел.

Первая ретроспектива показала, что ребята пошли разными путями. Кто-то взялся покрывать тестами код легаси калькулятора и рефакторить его, кто-то решил не трогать старый код а повторно реюзать его для чисел в 10-чной системе, предварительно перегнав их из римской, а после суммирования результат обратно в римскую систему. Умно! Хитро! Молодцы! Но мы попросили все же оставлять после себя систему чище и прозрачнее, чем она была до того как мы открыли код. Принцип скаута. 


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

Но мы не знаем, как код работает! Как писать test case? Воспользуемся brood force. Вот тест, написанный с помощью Approval Tests Library


Вот результат его выполнения проверенный Code Coverage tool (под Eclipse это EclEmma Plugin в IDEA Ultimate – Emma Plugin)



А в сырцах видно, какие строки не покрыты. Фидбек есть, а значит тест можно улучшить!


Ребятам библиотека понравилась. Следующая ретроспектива выявила ребят, которые решили разделять зависимости парсинга от калькуляции. Это и было наше следующее предложение ребятам.

Дело в том, что калькуляция чисел и парсинг их из x-ричного (а так же любого другого, например Римского) представления – две разные ответственности. А значит, если мы разместим их в одном классе – мы нарушим Single Responsibility Principle OOP. Суть его в том, что класс создается с одной и единственной целью и если в ходе его расширения появляется намек на новую роль – ее стоит выделить в отдельный метод, а потом и класс.


Вслед за этим стоит реализовать Inversion of Control принцип, который гласит
  • Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракции.
  • Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Одна из реализаций IoC принципа ООP – Dependency Injection. Суть ее лучше передаст Википедия

Внедрение зависимости (англ. Dependency injection) — процесс предоставления внешней зависимости программному компоненту. Является специфичной формой «обращения контроля (англ. Inversion of control)», где изменение порядка связи является путём получения необходимой зависимости. Условно, если объекту нужно получить доступ к определенному сервису, объект берет на себя ответственность за доступ к этому сервису: он или получает прямую ссылку на местонахождение сервиса, или обращается к известному «сервис-локатору» и запрашивает ссылку на реализацию определенного типа сервиса. Используя же внедрение зависимости, объект просто предоставляет свойство, которое в состоянии хранить ссылку на нужный тип сервиса; и когда объект создается, ссылка на реализацию нужного типа сервиса автоматически вставляется в это свойство (поле), используя средства среды. Внедрение зависимости более гибко, потому что становится легче создавать альтернативные реализации данного типа сервиса, а потом указывать, какая именно реализация должна быть использована в, например, конфигурационном файле, без изменений в объектах, которые этот сервис используют. Это особенно полезно в юнит-тестировании, потому что вставить реализацию «заглушки» сервиса в тестируемый объект очень просто. С другой стороны, излишнее использование внедрения зависимостей может сделать приложения более сложными и трудными в сопровождении: так как для понимания поведения программы программисту необходимо смотреть не только в исходный код, а еще и в конфигурацию, а конфигурация, как правило, невидима для IDE, которые поддерживают анализ ссылок и рефакторинг, если явно не указана поддержка фреймворков с внедрениями зависимостей.
Самой простой реализацией DI – является инъекция зависимости в зависимый класс через конструктор (в случае композиции), либо чрез set-метод (в случае более общей агрегации). В так на сцене появляется некий Class3, который проводит эту инъекцию, а потом делегирует выполнение Class1, который, в свою очередь, пользуется своей зависимостью Class2 под видом Interface2. Магия в том, что в Class1 можно вставить и другую реализацию Interface2 в том числе и Mock (а так же Stub, Fake, DummyObject, Spy, …) для целей тестирования.

После того, как абстракция и зависимость будут выделены – реализацию абстракции можно протестировать отдельно как unit (либо разработать по TDD). Так же можно протестировать и зависимый класс отдельно от зависимости, используя при этом Mock framework. Мы рекомендуем Mockito.



Замечательно то, что вы можете вести разработку зависимого Class1 с нуля (по TDD) при этом не имея на руках реализации зависимости (Class2), имея на руках всего лишь Абстракцию (Interface2). Реализацию зависимости (Class2) можно разработать позже, после того, как зависимый Class1 будет готов. Далее модули (Class1 и Class2) интегрируются и эту интеграцию так же стоит протестировать, ведь наличие одних только unit-тестов не гарантирует работоспособность системы.

Предложили попробовать разделить зависимости Калькуляции от Парсинга+Валидации и протестировать их отдельно (используя Mockito для Class1). Если задача (завоевания Рима) еще не решена, разработку (по ТДД) рекомендовали продолжать в русле шаблона Strategy.

А Рим так просто не сдавался. Причем мы с Сергеем явно недооценили эту задачу. Она съела наш мозг! Так продолжалось до самого вечера. Официального закрытия тренинга не было и это сделано было специально - дело в том, что закрывать рано. Все только начинается....

И потому, ребята, вот мой скайп - alexander.baglay - пишите с вопросами, будем рады помочь.

Обещанные книги для TDD практиков

Вся информация по Tetris Coding Dojo

Добавляйтесь к нам в Facebook-группу чтобы следить за новостями

А посмотреть, какие мы были красивые можно тут

Отдельное спасибо Саше из DIO Soft за помощь в организации конференца.


А так же Лине (ScrumGuides) за помощь в сборе группы и нарезании карточек Мир-Реальность.


Сережа, спасибо и тебе за то что ты такой клевый Напарник!


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