преобразования внутренней структуры программы при сохранении еѐ внешнего поведения. В его основе лежит последовательность небольших эквивалентных (т.е., сохраняющих поведение) преобразований Источник: http://ru.wikipedia.org/wiki/Рефакторинг «Безудержный Refactoring», (с) 2008 4 из 77
и добавления новой функциональности, но помогает избежать ошибок и облегчить добавление функциональности. Он выполняется для улучшения понятности кода или изменения его структуры, для удаления «мѐртвого кода» — всѐ это для того, чтобы в будущем код было легче поддерживать и развивать Источник: http://ru.wikipedia.org/wiki/Рефакторинг «Безудержный Refactoring», (с) 2008 5 из 77
Change Reference to Value • Change Unidirectional Association to Bidirectional • Change Value to Reference • Collapse Hierarchy • Consolidate Conditional Expression • Consolidate Duplicate Conditional Fragments • Convert Dynamic to Static Construction by Gerard M. Davison • Convert Static to Dynamic Construction by Gerard M. Davison • Decompose Conditional • Duplicate Observed Data • Eliminate Inter-Entity Bean Communication (Link Only) • Encapsulate Collection • Encapsulate Downcast • Encapsulate Field • Extract Class • Extract Interface • Extract Method • Extract Package by Gerard M. Davison • Extract Subclass • Extract Superclass • Form Template Method • Hide Delegate • Hide Method • Hide presentation tier-specific details from the business tier (Link Only) • Inline Class • Inline Method • Inline Temp • Introduce A Controller (Link Only) • Introduce Assertion • Introduce Business Delegate (Link Only) • Introduce Explaining Variable • Introduce Foreign Method • Introduce Local Extension • Introduce Null Object • Introduce Parameter Object • Introduce Synchronizer Token (Link Only) • Localize Disparate Logic (Link Only) • Merge Session Beans (Link Only) • Move Business Logic to Session (Link Only) • Move Class by Gerard M. Davison • Move Field • Move Method • Parameterize Method • Preserve Whole Object • Pull Up Constructor Body • Pull Up Field • Pull Up Method • Push Down Field • Push Down Method • Reduce Scope of Variable by Mats Henricson • Refactor Architecture by Tiers (Link Only) • Remove Assignments to Parameters • Remove Control Flag • Remove Double Negative by Ashley Frieze and Martin Fowler • Remove Middle Man • Remove Parameter • Remove Setting Method • Rename Method • Replace Array with Object • Replace Assignment with Initialization by Mats Henricson • Replace Conditional with Polymorphism • Replace Conditional with Visitor by Ivan Mitrovic • Replace Constructor with Factory Method • Replace Data Value with Object • Replace Delegation with Inheritance • Replace Error Code with Exception • Replace Exception with Test • Replace Inheritance with Delegation • Replace Iteration with Recursion by Dave Whipp • Replace Magic Number with Symbolic Constant • Replace Method with Method Object • Replace Nested Conditional with Guard Clauses • Replace Parameter with Explicit Methods • Replace Parameter with Method • Replace Record with Data Class • Replace Recursion with Iteration by Ivan Mitrovic • Replace Static Variable with Parameter by Marian Vittek • Replace Subclass with Fields • Replace Temp with Query • Replace Type Code with Class • Replace Type Code with State/Strategy • Replace Type Code with Subclasses • Reverse Conditional by Bill Murphy and Martin Fowler • Self Encapsulate Field • Separate Data Access Code (Link Only) • Separate Query from Modifier • Split Loop by Martin Fowler • Split Temporary Variable • Substitute Algorithm • Use a Connection Pool (Link Only) • Wrap entities with session (Link Only) «Безудержный Refactoring», (с) 2008 11 из 77
2008 14 из 77 • Чисто синтаксического анализа кода не хватает – нужен семантический (и зачастую весьма продвинутый) • Далее пример весьма распространенной ситуации с переименованием члена класса, имя которого используется как литерал • Современные инструменты решают эту проблему, но в полуавтоматическом режиме (т.е. остается место для ошибки!)
• Тыква => Карета • Длинные методы • Что такое «длинные»? Несколько экранов? • Есть и обратная ситуация (много мелких методов) • Дублирование кода «Безудержный Refactoring», (с) 2008 17 из 77
(с) 2008 18 из 77 public void PrintSpecialText() { PrintAlfa(); PrintBeta(); PrintGamma(); } private void PrintAlfa() { Console.WriteLine("alfa"); } private void PrintBeta() { Console.WriteLine("beta"); } private void PrintGamma() { Console.WriteLine("gamma"); } • Много мелких приватных методов, используемых в одном месте – тоже плохо (на ровном месте увеличивается «косвенность» при чтении кода) • Обратите внимание, что для многих рефакторингов есть обратные: • Extract Method • Inline Method
всё было бы проще! • За нас всѐ сделал бы компилятор: – Анонимные делегаты – Автоматические замыкания – И не надо городить иерархии классов… «Безудержный Refactoring», (с) 2008 31 из 77
ведьм» • Я видел много кода с большим дублированием, который было не сложно сопровождать и развивать • И видел код вообще без дублирования, который очень сложно развивать и сопровождать «Безудержный Refactoring», (с) 2008 35 из 77
2008 38 из 77 Кто изменил Что изменил Зачем изменил • Имея номер бага (дела, issue) нужно уметь отвечать • какие изменения в коде это повлекло? • кто их сделал? • А для фрагмента кода: • в связи с чем он написан/исправлен? • кто это сделал? • По номеру ревизии: • какие баги исправлены, какие фичи вошли?
кода, причем вкусовое (ни качества, ни понятности оно не добавило) • То, что действительно следовало бы поменять (заменить сложные условия на методы, избавиться от литеральных строк в пользу строковых констант и т.д.) – не сделано «Безудержный Refactoring», (с) 2008 46 из 77
– Новые модные паттерны и/или изменение в осознании «мировых истин» – Другой стандарт кодирования 2. Темная сторона инструментов автоматической проверки кода – Анекдот про то, кто такой зануда 3. «Я преобразую код, чтобы разобраться в нем» – Опасно, когда руки работают вперед головы! «Безудержный Refactoring», (с) 2008 47 из 77
императивных языках поведение одного и того же фрагмента кода может сильно отличаться в зависимости от «окружения» (side-эффекты) • Особенно остро это чувствуется при: – многопоточном программировании – работе с СУБД – взаимодействии с внешними системами и устройствами – GUI «Безудержный Refactoring», (с) 2008 48 из 77
когда они эффективны: – Контроль соглашений по именованию • при этом семантику названия они проверить не могут! – Контроль типичных «ляпов» a la catch (Exception) { /*пусто*/ } «Безудержный Refactoring», (с) 2008 53 из 77
MS Visual Studio 2005 SDK ver. 4.0 Скачать можно отсюда: • http://www.microsoft.com/downloads/details.aspx?familyid=51A5C65B-C020-4E08-8AC0- 3EB9C06996F4&displaylang=en Далее идут выдержки из файлов: • .\VSSDK40\MPF\Shell\TaskProvider.cs • .\VSSDK40\MPF\Shell\Package.cs «Безудержный Refactoring», (с) 2008 54 из 77
«волшебный» фрагмент кода с такими же «волшебными» комментариями: - что-то пытаемся сделать - а если не смогли, то это оказывается не проблема! (и можно ничего не делать…) - зачем тогда вообще пытались что-то сделать?!
же вставлена хоть какая-то диагностика. НО! Она будет только в Debug-варианте… А как разбираться и диагностировать проблемы, имея на руках только Release? Не лучше бы было писать файловый лог или использовать Windows Event Log, который как раз и задуман на случаи, когда программе надо на что-то пожаловаться, а куда жаловаться – не понятно ?!
исправление замечаний (без понимания, лишь бы отвязалась) • Ложное чувство уверенности в качестве кода • При этом, на настройку этих инструментов может уходить много сил «Безудержный Refactoring», (с) 2008 58 из 77
из 77 • Пример из жизни достаточно распространенного и опасного ляпа, который не ловится инструментами автоматической проверки кода: • Immutable (неизменный) класс для хранения многополевого первичного ключа
– прежде чем изменять код, его следует понять – прежде чем реализовывать новую функциональность, поищите – не реализовано ли уже где-то что-то аналогичное – если что-то не нравится в том, как аналогичную задачу решили до вас, то не надо молча делать новое по-своему, а старое оставлять по-прежнему (либо менять и там, и там, либо наступить себе на горло и делать аналогично старому) «Безудержный Refactoring», (с) 2008 66 из 77
– если объем исправлений мал и код не удовлетворяет текущим правилам форматирования, то исправления должны быть внесены в стиле форматирования существующего кода – если объем исправлений достаточно велик, то новые куски могут быть отформатированы в соответствии с текущими представлениями о правильном стиле, а форматирование остальных частей должно быть оставлено как есть – весь файл может быть переформатирован только в случае почти полного его переписывания (т.е. почти полной замены старой реализации на новую) «Безудержный Refactoring», (с) 2008 69 из 77
считаться "выполнением рефакторинга" – это допустимо выполнять (например, устранять warning-и ReSharper-а) только при условии необходимости внесения в данный файл существенных исправлений логики (мелкий патчинг, который выражается в правке одной-пяти строк кода не может считаться существенным исправлением) «Безудержный Refactoring», (с) 2008 70 из 77
инструментов (форматирования и проверки кода) • Причем эти настройки должны соответствовать принятым у вас соглашениям «Безудержный Refactoring», (с) 2008 73 из 77
(с) 2008 74 из 77 сборочный сервер коллега аналитик или PO демо (1) автоматические сборка + тесты (2) Code Review (3) Сделано то, что нужно? Оно работает? Это удобно? Feedback Feedback
и сразу после реализации бага (как часть Defenition- of-Done) 2. Пары автор-проверяющий должны образовываться «самопроизвольно» и меняться 3. Найденные недочеты лучше изложить в системе ведения дел, чтобы сам автор их устранил. Если их много и они сложные – проверяющий и автор садятся за клавиатуру вместе – это важно, чтобы был «обучающий» эффект (ошибки/проблемы больше не повторялись) – разногласия обсуждаются устно (можно с привлечением других членов команды) «Безудержный Refactoring», (с) 2008 75 из 77