На прошедший вебинар зарегистрировался 51 человек, около 30 приняли участие, из которых 20 держались все 3 часа. Я не стал выкладывать видео целиком, а разделил 3 часа на две логические части и убрал лишнее.
Это был довольно необычный опыт «парного программирования» — я за клавиатурой и 30 программистов обсуждают дальнейшие шаги. Часто спорили, иногда начинали говорить несколько человек одновременно.
Как всё проходило
Сценарий: нам (участникам вебинара) дали приложение — игра в покер по сети — и сказали, что некоторая функция в нем не работает. Чтобы ее поправить нам пришлось разбираться в коде и оценивать, что будет быстрее: отрефакторить код или написать всё с нуля.
Код был очень запутанным с названиями в переменных типа aaa, b, w и т.п. Вся бизнес-логика находилась в UI и одном классе с вложениями логических конструкций в 9 уровней.
Шаги по его рефакторингу
При работе с кодом совместно наметили два этапа.
На первом этапе надо сделать код читабельным и разобраться как он работает:
- Сделать Code Cleanup, чтобы отступы везде были одинаковые, выравнивания и т.п.
- Удалить весь закомментированный код
- Переименовать методы и переменные, дать им значимые имена (с нами был автор кода, чего в реальных условиях часто не бывает)
- Написать тесты на существующие куски кода, чтобы понять, как работает система
На втором этапе мы перерабатывали API и писали тесты:
- Через TDD выстроить своё API параллельно с существующим
- Скрыть части системы, которые будем рефакторить, за интерфейсы, чтобы остальная система ничего не узнала про рефакторинг (в этом могут помочь UML диаграммы и NDepend)
- Отрефакторить или переписать скрытую часть системы
Результаты
В целом я доволен этим экспериментом, был рад пообщаться с людьми из разных городов. Мне понравилось, что все не просто соглашались с одним мнением, а выдвигали свои. Уже поступили предложения повторить, но с некоторыми модификациями. Каким вы видите следующий вебинар из этой серии? Как можно улучшить формат? Как можно сделать вебинар более полезным?
Благодарности
Отдельное спасибо проекту SkillTrek, который предоставил свою площадку для вебинара.
Спасибо Тимуру за помощь в обработке видео.
Автору кода, Максиму, желаю успехов. Он умеет признавать свои ошибки и работать над ними, а это основа для развития.
Ссылки
Детали вебинара и исходный код проекта
Working Effectively with Legacy Code, Michael Feathers
Александр, спасибо. Было очень интересно поучаствовать в таком "эксперименте".
ОтветитьУдалитьПосмотрел видео, здорово! Жаль, не смог поучаствовать, были бы вопросы. Обсуждал со своими коллегами - типовые проблемы при добавлении новой функциональности были обозначены. На то, чтобы распилить проект и преобразовать 3-х часов недостаточно. Тем более, что приходится обсуждать те или иные действия. Мне понравилась фраза, что: "Давайте предлагайте решения, иначе те, кто молчат потом воспользуются своим молчанием, дабы сказать, что, дескать, надо было сделать по-другому" :)
ОтветитьУдалитьЕсли рассматривать конкретную задачу далее - там есть подводные камни и вряд ли метод GetBestCombination должен был быть у IPlayer. :)
Но, спасибо за вэбинар! При детальном обсуждении и озвучиванием хода мысли, очень интересно наблюдать. Общение в таком формате пока не видел, все заканчивается у других на "у нас тут есть небольшая домашняя заготовочка", - это угнетает :)
Прошу продолжать!!!
Рад, что вам понравилось. Какие будут предложение по продолжению?
ОтветитьУдалить>
ОтветитьУдалитьПрошу продолжать!!!
Чего делать будем?)
Я наверно очень счастливый программист и у меня ТАКОГО ужаса никогда не было. Хотелось бы посмотреть на рефакторинг и доработку реального проекта тысяч на 100 строчек кода, где есть базы данных, n-tier архитектура и другие элементы, которые не так просто покрыть тестами.
ОтветитьУдалитьРеальный пример из жизни: перевод приложения с DataSet'ов на Entity Framework параллельно с переносом бизнес-логики из БД на сервис.
Алексей, давайте ссылку на исходный код, который надо рефакторить.
ОтветитьУдалитьАлександр, а давай действительно реальный проект возьмем и порешаем над ним конкретные задачи. Жаль нет голосовалки, можно было бы выбрать тему вэбинара. Основа - чей-то проект. Вариант: через рефакторинг реального проекта к соблюдению принципов SOLID. Или брать отдельно - OCP, ISP, если недостаточно времени, например.
ОтветитьУдалитьНа лекции не присутствовал, но очень понравилось видео. Посмотрел за 2 подхода за 2 дня.
ОтветитьУдалитьОчень понравилась возможность послушать мнения других людей, а также наблюдать за процессом мышления и разработки тестов опытным TDD-практиком.
Хотелось бы поприсутствовать на следующем вебинаре. Судя во вашим ответам на комментарии в этом посте, Александр, вы ожидаете предложения по проведению следующих вебинаров.
Мое предложение такое - попробовать разрабатывать проект с нуля и уделить большое внимание вопросу разделения ответственностей. То есть хотелось бы послушать о принципах, умозаключениях, которыми вы пользуетесь, когда возникает сложность в понимании того, за что должен отвечать тот или иной класс.
Спасибо!
Денис, спасибо за предложение. Какой проект будем разрабатывать?
ОтветитьУдалитьКак насчет разработки модуля обработки принимаемых платежей с использованием бонусных кодов?
ОтветитьУдалитьДопустим, есть Пользователь, у которого есть Баланс.
Пользователь может пополнять Баланс.
Предположим, что нас не интересует, каким образом деньги поступают в систему, просто есть факт, что платеж прошел, и модуль должен пополнить пользователю Баланс.
Но самое интересное, что пользователь во время формирования счета на оплату может воспользоваться бонусным кодом, который хранится в каком-либо хранилище. Бонусный код увеличивает сумму зачисления на какой-либо процент.
Можно развить данную идею. Думаю это будет интересно тем, кто занимается созданием монетизируемых веб-сервисов.
Конкретно мне в этом рассматриваевом проекте было бы непонятно, как разделить логику работы бонусных кодов. Необходимо ли создать отдельный сервис по работе с этими кодами, либо же данный функционал можно оставить в сервисе Приема платежей (пополнения баланса пользователей) и т.д.
На мой взгляд, разработка проекта с нуля не позволит выявить нарушения принципов SOLID, потому что мы опять столкнемся с тем, что кол-во User Stories будет достаточно лишь для того, чтобы решить проблему на конкретном этапе. И, конечно, мы ее решим, ведь это проект с нуля! Таких недостатков лишен законченный проект, там однозначно будут разбухнувшие сервисы и другие вещи, не отвечающие принципам SOLID. Рефакторить, конечно, сложнее. Но profit, который можно получить, разбирая его по кускам, значительно выше. Мало кто озвучил, но текущий проект игры в покер был наделен исключительно процедурным подходом написания и реализации алгоритмов. И, важный момент: именно отсутствие ООП-дизайна привело нас к тому, что мы начали разработку API через TDD. По сути, мы занялись проектированием с нуля. Второй важный момент - у нас был на связи разработчик. Мы не смогли бы проектировать новый API, если бы специалист предметной области не передал нам знаний о домене. Таким знанием обладал Максим, если я не ошибаюсь с именем. В реальных жизненных проектах, конечно, будет по-другому. Там будет присутствовать в каком-то виде ООП-дизайн, будут неправильно выделены слои и будет размыта ответственность классов и много чего другого. И у нас не будет человека на связи, который сможет объяснить суть какого-то алгоритма, поэтому это вынудит нас рефакторить именно тот код, который _работает_. Я за рефакторинг реального проекта :)
ОтветитьУдалитьРискну отметить преимущества для участника каждого типа вебинара:
ОтветитьУдалить1. Рефакторинг:
- возможность наблюдать ошибки другого программиста при раработке, чтобы в дальнейшем их избежать;
- возможность увидеть на практике применение принципов улучшения кода.
2. Разработка с нуля:
- возможность увидеть ход мыслей, который приводит к написанию качественного кода сразу.
Думаю здесь нужно просто посчитать мнения людей, кому что больше будет по душе. В любом случае любая тема будет полезна и интересна.
Про Analizer улыбнуло...
ОтветитьУдалить2. Качественный код сразу пишется только при наличии большого опыта разработки аналогичных приложений, когда тупиковые (в данном контексте) решения отбрасываются даже без анализа последствий их применения. Передать опыт на словах за несколько минут не реально, а так всё отведенное время можно обсуждать плюсы и минусы TableDataGate, ActiveRecord и DataMapper+Repository (или Query)+UoW. Разве что искусственно выбирать "антипаттерн", искусственно натыкаться на его грабли, а потом как бы случайно предлагать более подходящий вариант.
ОтветитьУдалитьБыло бы неплохо сделать подобную практику периодической - раз или два раза в неделю. Например разработать какой-либо проект с нуля. Такого вот рода коллективная разработка. По-моему общий фан и неоценимый опыт всем участвующим будет обеспечен.
ОтветитьУдалитьПоддерживаю. Сам давно хотел переделывать свой проект написанный с использованием DataSet'ов, но застрял на этапе обдумывания)
ОтветитьУдалитьВообще интересно, есть ли место для TDD в CRUD приложениях, ведь та не так много логики которую нужно тестить?
Сергей, если логики действительно мало, то TDD будет хорошо применимо в самом начале проекта для проектирования и в дальнейшем, когда логики в проекте начнет прибавляться. Возможно это будет Test Last, а не Test First.
ОтветитьУдалитьМне понравилось видео, хотя я его еще не досмотрел до конца, жаль, что не мог поучаствовать из-за низкой скорости соединения.
ОтветитьУдалитьПредлагаю в следующем вебинаре хотя бы один человек из всей толпы народу сидел с открытой вкладкой онлайн-словаря и давал мгновенные консультации, потому что некоторые названия переменных сбивали с толку не хуже а1 и р3.
Далее - ввести какое-то правило по отключению звука людей с неисправными/фонящими микрофонами.
Влад, спасибо за обратную связь.
ОтветитьУдалитьКак всё закончилось для Максима :)
ОтветитьУдалитьПроект он переписал и с какого-то раза сдал мне зачет. К сожалению, у него так и не получилось уйти от процедурного подхода.
Начал копать про TDD набрел на ваш блог и посмотрел все 3 часа. Пожалел что не участвовал. Уж очень вы просто и доходчиво объясняете. Я пишу (пытаюсь писать), локальную реализацию Google Ants(заканчиваю 3ий курс). Это конечно громко сказано, но я пытаюсь писать максимально применяя свои знания на практике. Если будет еще подобный вебинар, готов предоставить свой код для растерзания). Спасибо вам за провсещение в TDD.
ОтветитьУдалитьВы можете прислать код мне на почту.
ОтветитьУдалитьАлександр, еще раз замечу, что лекция была просто шикарна. Может быть стоит повторить на проекте более-менее приближенному к ООП, чтобы можно было что-то отрефакторить, применить шаблоны и т.п.? На том же движке, например, что прошла online-конференция dotnetconf? Это реально что-то другое, чего не было еще в сети. По крайней мере, я не встречал такого. Что думаешь?
ОтветитьУдалитьДа, я хочу сделать серию подобных встреч. Надо собрать интересные темы. Я бы сейчас сделал пару вебинаров по ASP.NET MVC.
ОтветитьУдалитьНа счет рефакторинга, какой код вы предлагаете?
Ну, своя рубашка всегда ближе к телу. :)
ОтветитьУдалитьИз наших проектов с открытым исходным кодом, можем вместе посмотреть на http://webtasks.codeplex.com/.
Есть проблемные места, где хотелось бы получить рекомендации по исполнению. Из этого можно было бы неплохое видео снять.
Исходный код до или после рефакторинга?
ОтветитьУдалитьОлег, еще нужна помощь?
ОтветитьУдалитьИсходный код на Google Code, первая ревизия, как было в самом начале, последняя - что успели сделать
ОтветитьУдалитьAlex, я бы не отказался от пары-тройки советов по улучшению :)
ОтветитьУдалитьОк, гляну. Тебе куда писать?
ОтветитьУдалитьСпасибо, нашел первую ревизию.
ОтветитьУдалитьAlex, на menozgrande@gmail.com, если найдете время.. :)
ОтветитьУдалить