Всё, что вы хотели узнать о рефакторинге, но боялись спросить

    Господа, рад представить вам свой новый проект — Refactoring.guru.

    Сайт представляет собой каталог запахов грязного кода и, собственно, самих приёмов рефакторинга. В двух словах — это как книга Мартина Фаулера, но лучше. А именно:

    • Весь контент доступен на русском языке. Я старался делать описания как можно более живыми, чтобы избавиться от чувства унылости и скуки, которое возникает при чтении любой переводной книги о рефакторинге.
    • Все примеры подаются на Java и PHP. Другие языки обязательно будут добавляться со временем, но я пока затрудняюсь решить, каким будет следующий, можете предлагать в комментах.
    • Всё везде перелинковано. Рефакторинги сгруппированы по предназначениям и связям.


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

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

    Буду рад всем отзывам и пожеланиям! (а также лайкам и твитам)

    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 57
    • +3
      Хороший портал, к сожалению нашел пару ссылок, с объяснением паттернов на аналогичный англоязычный ресурс.
      Конечно, хотелось бы не париться в сложностях перевода и почитать на родном. Но, думаю, скоро автор портала дополнит этот материал на своём ресурсе.

      А картинки — вообще прелесть.

      Что можно добавить: паттерны реализации на разных языках программирования.
      • +4
        В дополнение к вышесказанному: очень понравилась интерактивность рефакторинга. Все разложенно по полочкам.
        еще раз, хочу поблагодарить за полезный ресурс.
      • +11
        Javascript должен быть следующим добавленным языком.
        • +9
          Вы ведь планируете расширять это на другие языки? Создайте репозиторий, да принимайте пулл-реквесты от желающих помочь — такие, я думаю, найдутся.
          • +2
            Было бы здорово иметь возможность скачать материалы в формате электронных книг (.mobi, ...)
            • 0
              тогда вся фишка интерактивности исчезнет
              • 0
                Для интерактивности читаем портал. Для чтения больших статей во время поездки в метро, мобильная offline версия самое оно, имхо.
              • +5
                Не проще ли тогда купить книгу по рефакторингу?
              • +5
                Сам по себе сайт очень красивый и приятный. Воздушный как зефир. Жаль что нет Javascript…
                • +1
                  С JS проблема в том, что там актуальны наверное только половина рефакторингов, т.к. нет настоящей поддержки ООП, с наследованием областями видимости и другими фичами. Но я подумаю, что можно сделать. Как минимум первые главы точно можно будет перевести на JS.
                  • +1
                    Думаю проблема не в JS, а в том что Фаулеровский рафакторинг написан под java и иже с ней. Естесвенно часть рефакторингов универсальна, а часть специфична для языка (группы языков).
                    • –4
                      Если использовать CoffeScript, то появляются классы и практически ООП.
                      • 0
                        ES6 вам в помошь
                        • +2
                          А ООП обязателен для рефакторинга, что ли? Речь должна идти не о том, чтобы портировать имеющиеся главы на JS, а о том, чтобы добавить приемы рефакторинга, актуальные для этого языка. Всё-таки он сильно отличается от Java и PHP.
                          • +1
                            > нет настоящей поддержки ООП
                            ООП это парадигма, а не обязательное присутствие в языке классов или ещё чего другого. Хотите сказать, что в JS нет поддержки инкапсуляции, полиморфизма или наследования? Всё это есть, только не в том виде, в которым вы привыкли видеть (class B extends A, хотя и этот сахарок уже добавили в ES6, как написали выше).

                            В Си тоже нет, с вашей точки зрения, ни наследования, ни областей видимости (я так понимаю, подразумевались пространства имён, namespaces) и, тем не менее, там есть наборы библиотек (самый известный пример это, наверное, en.wikipedia.org/wiki/GLib на базе GObject), которые написаны с применением ОО парадигмы.
                            • 0
                              Просто люди привыкли, что OOP — это class based концепция, а альтернативные (прототипные как в языке self ) им непривычны
                        • +2
                          Прекрасный портал и «интерактивные примеры с объяснениями» покорили.

                          И да — я голосую за javascript.
                          • +1
                            Ответил выше про JS.
                          • 0
                            Пользуясь случаем задам автору и читателям вопрос. Если есть стастические анализаторы кода, почему бы не сделать автоматический рефакторер?

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

                            Критерий оптимизации — соответствие формальным критериям в книжке и уменьшающийся объём кода.
                            • +2
                              Под «автоматическим» вы это имеете ввиду?

                              image
                              • 0
                                Да, именно так :)
                                Примеры похожих реализованных кнопок — GPS-навигаторы, поисковые сервера, пицца на заказ и прочие усовершенствования в жизни.
                              • 0
                                посмотрите на продукты jetbrains. Там автоматизированный рефакторинг. Полностью автоматический вряд ли можно сделать — кто будет придумывать идентификаторы для методов и т.д.
                                • –1
                                  Там рефакторинг «вручную», но с правилами, которые могут лечь в основу рефакторинга автоматического. А идентификаторы — да, генерить на основе имеющихся, типа FooSubmethod1()
                                  • +2
                                    > генерить на основе имеющихся, типа FooSubmethod1()

                                    Попробуйте обфускатор
                              • +1
                                Вроде бы знаешь один язык, разберешься и в остальных… Но любителей Яваскрипта это, кажется, не касается.

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

                                P.S. Автор молодец, и сайт симпатишный.
                                • +1
                                  Оно-то так, но каждый человек желает «ещё больше» комфорта. Ну и некоторые моменты всё же отличаются, их очень мало, но они есть.
                                • 0
                                  Оффтоп.

                                  Не очень люблю крупный шрифт (дело вкуса), игралась с масштабом и в 90% получила не слишком приятный «наезд» подчеркивания:

                                  image

                                  Маньяк внутри полез смотреть верстку и обнаружил:

                                  p a { text-decoration: none; background-image: -webkit-linear-gradient(top,#fff 50%,#3a3a3c 50%); background-image: linear-gradient(to bottom,#fff 50%,#3a3a3c 50%); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ff3a3a3c', GradientType=0); background-size: 2px 2px; background-position: 0 1em; }

                                  Почему именно так? Любопытно, есть ли преимущество в таком способе обычного подчеркивания? (с кастомным все понятно).
                                  • 0
                                    Насколько я понимаю, так получается, всё-таки, не обычное подчёркивание, а тонкое, однопиксельное. Сравните:

                                    • 0
                                      Да, но между использованием text-decoration и background еще есть более простой border:

                                      • 0
                                        Border, как правильно, отображает черту на несколько пикселей ниже, чем при обычном подчёркивании.
                                        • +1
                                          В итоге, не сработала часть вашей картинки по поводу подчёркивания:
                                          image
                                    • 0
                                      Вот здесь описаны и причины и техника: medium.com/designing-medium/crafting-link-underlines-on-medium-7c03a9274f9
                                      • 0
                                        Большое спасибо! Чего-то такого и ожидала.

                                        А по поводу «наезда» при 90% масштабе, заменила background-position: 0 1em; на background-position: 0 23px; и все стало смотреться идеально.
                                    • +1
                                      Классный сайт, все очень понравилось. Чуть-чуть с величиной заголовков автор переборщил на мой взгляд, а так все очень здорово. Дизайн немного похож на англоязычный sourcemaking.com, наверное, он служил примером.
                                      Еще раз спасибо :)
                                      • +4
                                        Очень было бы интересно взглянуть на питоновские примеры.
                                        • +4
                                          Я бы даж поспособствовал их написанию :)
                                          • 0
                                            Если есть желание и возможность, можно помочь с переводом примеров. Вот репозиторий с текущими примерами: github.com/shvetsgroup/refactoring.guru-examples

                                            Буду рад пулл-реквестам! :)
                                        • +1
                                          У Вас ошибка в живом примере на Java refactoring.guru/replace-method-with-method-object:
                                          В шаге 5 отсутствует замена локальных переменных приватным полями.
                                          Хорошо бы добавить кнопку «Сообщить об ошибке».
                                          А так сайт отличный, однозначно в избранное!
                                          • 0
                                            Большое спасибо, исправил этот момент. Кстати, там если справа на странице зеленая плашка, ведущая на под-сайт поддержки, вот там можно оставлять сообщения об ошибках.
                                          • +1
                                            Мартин Фаулер в своей книге уделяет большое внимание юнит тестам. Если код не покрыт юнит тестами, то рефакторинг такого кода становится опасным.
                                            Хорошо бы упомянуть как-то этот момент на Вашем сайте, допустим в интерактивных примерах можно добавить шаг с запуском юнит тестов, и т.п.
                                            • +3
                                              neochief с меня печеньки, куда выслать?
                                              • –2
                                                Страницы грузятся очень медленно, вплоть до подвисания всего браузера на несколько секунд. Скорее всего из-за этих никому не нужных социальных кнопок.
                                                • 0
                                                  хабраэффект же
                                                • 0
                                                  В этом примере на выходе получаем код, в котором метод описан внутри тела конструктора и при этом виден из другого класса. Если просмотреть пример до конца, то после того как рефакторинг закончен начинает творится что-то странное ( Ну или так отработало показать изменения.
                                                  • 0
                                                    Спасибо, это жирная бажина, которую я только что исправил.
                                                  • 0
                                                    Отлично, спасибо!
                                                    • 0
                                                      В живом примере с PHP ошибка на последнем шаге.
                                                      вместо

                                                      return outstanding;
                                                      


                                                      должно быть

                                                      return $outstanding;
                                                      
                                                    • 0
                                                      Спасибо огромное, сайт просто великолепный, интерактивные примеры сделаны очень круто. Был бы рад увидеть среди них примеры на python.
                                                      Ни в коем случае не переделывайте дизайн — он идеален.
                                                      • 0
                                                        Всё также. С ходе примера метод compute оказывается внутри тела конструктора. Хотя должен быть отдельным методом в классе.
                                                        class Gamma {
                                                          private final Account _account;
                                                          private int importantValue1;
                                                          private int importantValue2;
                                                          private int importantValue3;
                                                          private int inputVal;
                                                          private int quantity;
                                                          private int yearToDate;
                                                          public Gamma(Account source, int inputValArg, int quantityArg, int yearToDateArg) {
                                                            _account = source;
                                                            inputVal = inputValArg;
                                                            quantity = quantityArg;
                                                            yearToDate = yearToDateArg;
                                                            public int compute() {
                                                              int importantValue1 = (inputVal * quantity) _account.delta()();
                                                              int importantValue2 = (inputVal * yearToDate) + 100;
                                                              if ((yearToDate - importantValue1) > 100) {
                                                                importantValue2 -= 20;
                                                              }
                                                              int importantValue3 = importantValue2 * 7;
                                                              // и так далее...
                                                              return importantValue3 - 2 * importantValue1;
                                                            }
                                                          } 
                                                        } 
                                                        
                                                        • 0
                                                          Это кеш. Стоит почистить и все появится.
                                                        • 0
                                                          refactoring.guru/replace-temp-with-query
                                                          результирующий код может получить дополнительную нагрузку за счёт вызова нового метода. Однако, в наше время быстрых процессоров и хороших компиляторов, такая нагрузка вряд ли будет заметна

                                                          больше всего в книжках про красивые рефакторинги смущают такие моменты. в теории, да, может быть, а на деле? рядом с примерами «до» и «после» было бы крайне познавательно видеть живые пузомерки, чтобы оценить масштаб бедствия на практике. ведь наверняка, для Java и PHP последствия могут быть сильно разными.

                                                          ps: вот что-то меня гложат сильные сомнения, что «быстрые процессоры и хорошие компиляторы» интерпретируемых языков будут рады такому рефакторингу. накидал для JS jsperf.com/replace-temp-with-query — как и предполагалось, результат стал медленнее на половину ;-/
                                                          • 0
                                                            > как и предполагалось, результат стал медленнее на половину ;-/

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

                                                            Но я не думаю, что написание пузомерок — это типовой кейс. Я даже больше скажу, для написания пузомерок лучше JS вообще не брать — рискуете больше, чем в 2 раза проиграть.
                                                          • 0
                                                            Было бы неплохо обновления через rss получать.
                                                            • 0
                                                              спасибо, почитал, затянуло аж до утра)
                                                              • 0
                                                                1. Берем книгу Мартина Фаулера — Рефакторинг
                                                                2. Создаем перелинкованный ресурс по книге, аля wiki
                                                                3. ???
                                                                4. PROFIT!

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

                                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.