18 декабря 2011 г.

Видео. Онлайн лекция по Refactoring Legacy Code

На прошедший вебинар зарегистрировался 51 человек, около 30 приняли участие, из которых 20 держались все 3 часа. Я не стал выкладывать видео целиком, а разделил 3 часа на две логические части и убрал лишнее.

Это был довольно необычный опыт «парного программирования» — я за клавиатурой и 30 программистов обсуждают дальнейшие шаги. Часто спорили, иногда начинали говорить несколько человек одновременно.

Как всё проходило

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

Код был очень запутанным с названиями в переменных типа aaa, b, w и т.п. Вся бизнес-логика находилась в UI и одном классе с вложениями логических конструкций в 9 уровней.

Шаги по его рефакторингу

При работе с кодом совместно наметили два этапа.

На первом этапе надо сделать код читабельным и разобраться как он работает:

  1. Сделать Code Cleanup, чтобы отступы везде были одинаковые, выравнивания и т.п.
  2. Удалить весь закомментированный код
  3. Переименовать методы и переменные, дать им значимые имена (с нами был автор кода, чего в реальных условиях часто не бывает)
  4. Написать тесты на существующие куски кода, чтобы понять, как работает система

На втором этапе мы перерабатывали API и писали тесты:

  1. Через TDD выстроить своё API параллельно с существующим
  2. Скрыть части системы, которые будем рефакторить, за интерфейсы, чтобы остальная система ничего не узнала про рефакторинг (в этом могут помочь UML диаграммы и NDepend)
  3. Отрефакторить или переписать скрытую часть системы

Результаты

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

Благодарности

Отдельное спасибо проекту SkillTrek, который предоставил свою площадку для вебинара.

Спасибо Тимуру за помощь в обработке видео.

Автору кода, Максиму, желаю успехов. Он умеет признавать свои ошибки и работать над ними, а это основа для развития.


Ссылки

Детали вебинара и исходный код проекта

Working Effectively with Legacy Code, Michael Feathers

Видео. Пример разработки приложения с помощью TDD

32 комментария:

  1. Сергей Шувалов22 декабря 2011 г., 22:47

    Александр, спасибо. Было очень интересно поучаствовать в таком "эксперименте".

    ОтветитьУдалить
  2. Посмотрел видео, здорово! Жаль, не смог поучаствовать, были бы вопросы. Обсуждал со своими коллегами - типовые проблемы при добавлении новой функциональности были обозначены. На то, чтобы распилить проект и преобразовать 3-х часов недостаточно. Тем более, что приходится обсуждать те или иные действия. Мне понравилась фраза, что: "Давайте предлагайте решения, иначе те, кто молчат потом воспользуются своим молчанием, дабы сказать, что, дескать, надо было сделать по-другому" :)
    Если рассматривать конкретную задачу далее - там есть подводные камни и вряд ли метод GetBestCombination должен был быть у IPlayer. :)
    Но, спасибо за вэбинар! При детальном обсуждении и озвучиванием хода мысли, очень интересно наблюдать. Общение в таком формате пока не видел, все заканчивается у других на "у нас тут есть небольшая домашняя заготовочка", - это угнетает :)
    Прошу продолжать!!!

    ОтветитьУдалить
  3. Рад, что вам понравилось. Какие будут предложение по продолжению?

    ОтветитьУдалить

  4. Прошу продолжать!!!
    Чего делать будем?)

    ОтветитьУдалить
  5. Я наверно очень счастливый программист и у меня ТАКОГО ужаса никогда не было. Хотелось бы посмотреть на рефакторинг и доработку реального проекта тысяч на 100 строчек кода, где есть базы данных, n-tier архитектура и другие элементы, которые не так просто покрыть тестами.

    Реальный пример из жизни: перевод приложения с DataSet'ов на Entity Framework параллельно с переносом бизнес-логики из БД на сервис.

    ОтветитьУдалить
  6. Алексей, давайте ссылку на исходный код, который надо рефакторить.

    ОтветитьУдалить
  7. Александр, а давай действительно реальный проект возьмем и порешаем над ним конкретные задачи. Жаль нет голосовалки, можно было бы выбрать тему вэбинара. Основа - чей-то проект. Вариант: через рефакторинг реального проекта к соблюдению принципов SOLID. Или брать отдельно - OCP, ISP, если недостаточно времени, например.

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

    Хотелось бы поприсутствовать на следующем вебинаре. Судя во вашим ответам на комментарии в этом посте, Александр, вы ожидаете предложения по проведению следующих вебинаров.

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

    Спасибо!

    ОтветитьУдалить
  9. Денис, спасибо за предложение. Какой проект будем разрабатывать?

    ОтветитьУдалить
  10. Как насчет разработки модуля обработки принимаемых платежей с использованием бонусных кодов?

    Допустим, есть Пользователь, у которого есть Баланс.
    Пользователь может пополнять Баланс. 

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

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

    Можно развить данную идею. Думаю это будет интересно тем, кто занимается созданием монетизируемых веб-сервисов.

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

    ОтветитьУдалить
  11. На мой взгляд, разработка проекта с нуля не позволит выявить нарушения принципов SOLID, потому что мы опять столкнемся с тем, что кол-во User Stories будет достаточно лишь для того, чтобы решить проблему на конкретном этапе. И, конечно, мы ее решим, ведь это проект с нуля! Таких недостатков лишен законченный проект, там однозначно будут разбухнувшие сервисы и другие вещи, не отвечающие принципам SOLID. Рефакторить, конечно, сложнее. Но profit, который можно получить, разбирая его по кускам, значительно выше. Мало кто озвучил, но текущий проект игры в покер был наделен исключительно процедурным подходом написания и реализации алгоритмов. И, важный момент: именно отсутствие ООП-дизайна привело нас к тому, что мы начали разработку API через TDD. По сути, мы занялись проектированием с нуля. Второй важный момент - у нас был на связи разработчик. Мы не смогли бы проектировать новый API, если бы специалист предметной области не передал нам знаний о домене. Таким знанием обладал Максим, если я не ошибаюсь с именем. В реальных жизненных проектах, конечно, будет по-другому. Там будет присутствовать в каком-то виде ООП-дизайн, будут неправильно выделены слои и будет размыта ответственность классов и много чего другого. И у нас не будет человека на связи, который сможет объяснить суть какого-то алгоритма, поэтому это вынудит нас рефакторить именно тот код, который _работает_. Я за рефакторинг реального проекта :)

    ОтветитьУдалить
  12. Рискну отметить преимущества для участника каждого типа вебинара:

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

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

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

    ОтветитьУдалить
  13. Владимир Чернышев29 декабря 2011 г., 5:36

    2. Качественный код сразу пишется только при наличии большого опыта разработки аналогичных приложений, когда тупиковые (в данном контексте) решения отбрасываются даже без анализа последствий их применения. Передать опыт на словах за несколько минут не реально, а так всё отведенное время можно обсуждать плюсы и минусы TableDataGate, ActiveRecord и DataMapper+Repository (или Query)+UoW. Разве что искусственно выбирать "антипаттерн", искусственно натыкаться на его грабли, а потом как бы случайно предлагать более подходящий вариант.

    ОтветитьУдалить
  14. Михаил Корчак4 января 2012 г., 0:31

    Было бы неплохо сделать подобную практику периодической - раз или два раза в неделю. Например разработать какой-либо проект с нуля. Такого вот рода коллективная разработка. По-моему общий фан и неоценимый опыт всем участвующим будет обеспечен.

    ОтветитьУдалить
  15. Поддерживаю. Сам давно хотел переделывать свой проект написанный с использованием DataSet'ов, но застрял на этапе обдумывания)
    Вообще интересно, есть ли место для TDD в CRUD приложениях, ведь та не так много логики которую нужно тестить?  

    ОтветитьУдалить
  16. Сергей, если логики действительно мало, то TDD будет хорошо применимо в самом начале проекта для проектирования и в дальнейшем, когда логики в проекте начнет прибавляться. Возможно это будет Test Last, а не Test First.

    ОтветитьУдалить
  17. Мне понравилось видео, хотя я его еще не досмотрел до конца, жаль, что не мог поучаствовать из-за низкой скорости соединения. 

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

    Далее - ввести какое-то правило по отключению звука людей с неисправными/фонящими микрофонами. 

    ОтветитьУдалить
  18. Влад, спасибо за обратную связь.

    ОтветитьУдалить
  19. Как всё закончилось для Максима :)
    Проект он переписал и с какого-то раза сдал мне зачет. К сожалению, у него так и не получилось уйти от процедурного подхода.

    ОтветитьУдалить
  20. Андрей Иванов30 апреля 2012 г., 6:16

    Начал копать про TDD набрел на ваш блог и посмотрел все 3 часа. Пожалел что не участвовал. Уж очень вы просто и доходчиво объясняете. Я пишу (пытаюсь писать), локальную реализацию Google Ants(заканчиваю 3ий курс). Это конечно громко сказано, но я пытаюсь писать максимально применяя свои знания на практике. Если будет еще подобный вебинар, готов предоставить свой код для растерзания). Спасибо вам за провсещение в TDD.

    ОтветитьУдалить
  21. Вы можете прислать код мне на почту.

    ОтветитьУдалить
  22. Александр, еще раз замечу, что лекция была просто шикарна. Может быть стоит повторить на проекте более-менее приближенному к ООП, чтобы можно было  что-то отрефакторить, применить шаблоны и т.п.? На том же движке, например, что прошла online-конференция dotnetconf? Это реально что-то другое, чего не было еще в сети. По крайней мере, я не встречал такого. Что думаешь?

    ОтветитьУдалить
  23. Alexander Byndyu5 мая 2012 г., 17:30

    Да, я хочу сделать серию подобных встреч. Надо собрать интересные темы. Я бы сейчас сделал пару вебинаров по ASP.NET MVC.

    На счет рефакторинга, какой код вы предлагаете?

    ОтветитьУдалить
  24. Ну, своя рубашка всегда ближе к телу. :)
    Из наших проектов с открытым исходным кодом, можем вместе посмотреть на http://webtasks.codeplex.com/.
    Есть проблемные места, где хотелось бы получить рекомендации по исполнению. Из этого можно было бы неплохое видео снять.

    ОтветитьУдалить
  25. Исходный код до или после рефакторинга?

    ОтветитьУдалить
  26. Исходный код на Google Code, первая ревизия, как было в самом начале, последняя - что успели сделать

    ОтветитьУдалить
  27. Alex, я бы не отказался от пары-тройки советов по улучшению :)

    ОтветитьУдалить
  28. Ок, гляну. Тебе куда писать?

    ОтветитьУдалить
  29. Спасибо, нашел первую ревизию.

    ОтветитьУдалить
  30. Alex, на menozgrande@gmail.com, если найдете время.. :)

    ОтветитьУдалить