Код с запашко́м — термин, обозначающий код с признаками (запахами) проблем в системе. Был введен Кентом Беком и использован Мартином Фаулером в его книге Рефакторинг. Улучшение существующего кода, с тех пор активно используется разработчиками ПО.. Купить книгу «Рефакторинг. Улучшение существующего кода» автора Мартин Фаулер и другие произведения в разделе Книги в интернет-магазине .
Техника: Составление методов (рефакторинг М. Фаулера)Синтаксис будет на C#, но главное понимать идею, а её можно использовать в любом другом языке программирования. Составление методов. Выделение метода (преобразуйте фрагмент кода в метод, название которого объясняет его значение). Длинный метод разбиваем на логические под- методы. Fromvoid Print. User. Info(decimal amount){Print.
- Рефакторинг. Улучшение существующего кода. Автор. Фаулер М. Издательство. Каждый шаг рефакторинга прост. Это может быть перемещение поля из одного класса в другой, вынесение фрагмента кода из метода и превращение его в самостоятельный метод или даже..
- Мартин Фаулер. Рефакторинг. Улучшение существующего кода. Перевод С. Маккавеева. Фаулер М. Рефакторинг: улучшение существующего кода. - Пер. с англ. - СПб: Символ-Плюс, 2007. - 432 с, ил.
- Books.Ru – Книги: Рефакторинг : улучшение существующего кода купить цена, заказ, оптом, отзывы, Фаулер Бек Брант Робертс Апдайк, ISBN.
Parent. Info(); Console. Write. Line(string. Format("имя: {0}", name); Console. Write. Line(string. Format("возраст: {0}", age); Console.
Write. Line(string. Format("кол- во: {0}", amount); }Tovoid Print. User. Info(decimal amount){Print. Parent. Info(); Print. User. Details(decimal amount); }void Print. User. Details(decimal amount){Console.
Write. Line(string. Format("имя: {0}", name); Console.
Write. Line(string. Format("возраст: {0}", age); Console.
Write. Line(string. Format("кол- во: {0}", amount); }Встраивание метода (поместите тело метода в код, который его вызывает и удалите метод). Излишняя косвенность (разбивка на методы) может усложнить класс.
Fromint Get. Points(){return Has. Max. Sum() ? decimal.
One : decimal. Zero; }bool Has. Max. Sum(){return summ > = max.
Summ; }Toint Get. Points(){return summ > = max. Summ ? decimal. One : decimal. Zero; }Встраивание временной переменной (замените этим выражением, все ссылки на данную переменную).
Лишний промежуточный код. Fromdecimal cost = order. Get. Cost(); return cost > 1. Toreturn order. Get. Cost() > 1. 00. Замена временной переменной вызовом метода (преобразуйте выражение в метод).
Метод может вызываться в любом месте класса, если таких мест много. Fromdecimal Method. A(){decimal summ = amount * cost; if(summ > 1. Method. B(){//do somethingdecimal summ = amount * cost; return summ != 0 ? Todecimal Method.
A(){decimal summ = Get. Summ(); if(summ > 1. Method. B(){//do somethingreturn Get. Summ() != 0 ? Get. Summ() * 1. 00 : 1; }decimal Get. Summ(){return amount * cost; }Введение поясняющей переменной (поместите результат выражения или его части во временную переменную).
Упрощается чтение и понимание кода. Fromif(Visual. Items. Column. Count == Focused. Cell. X & & (key == Keys. Alt | Keys. Shift) & & Was. Initialized() & & (resize > 0)){// do something}Tobool is. Last. Focused. Column = Visual.
Items. Column. Count == Focused. Cell. X; bool alt. Shift. Pressed = (key == Keys. Alt | Keys. Shift); bool was.
Resized = resize > 0; if(is. Last. Focused. Column & & alt. Shift. Pressed & & Was. Initialized() & & was. Resized){// do something}Расщепление поясняющей переменной (создайте для каждого присвоения отдельную временную переменную). Упрощается чтение и понимание кода. Fromdecimal temp = 2 * (height + width); Console.
Write. Line(temp); temp = height * width; Console. Write. Line(temp); Todecimal perimetr = 2 * (height + width); Console. Write. Line(perimetr); decimal area = height * width; Console.
Write. Line(area); Удаление присвоений параметрам (лучше воспользоваться временной переменной). Методы не должны менять значения входящих параметров, если это явно не указано (например out, ref в C#). Fromint Discount(int amount, bool use. Default. Discount, Date. Time date){if(amount == 0 & & use.
Default. Discount){amount = 1. Toint Discount(int amount, bool use. Default. Discount, Date. Time date){int result = amount; if(value == 0 & & use. Default. Discount){result = 1. Замена метода объектом методов (преобразуйте метод в отдельный объект). Декомпозиция класса для гибкости кода.
Fromclass Message. Sender{public Send(string title, string body){// do something// long calculation of some conditionif(condition){// sending message }}}Toclass Message. Sender{public Send(string title, string body, decimal percent, int quantity){// do something. Condition condition = new Condition (percent, quantity, date. Time); if(condition. Calculate()){// sending message }}}class Condition{public Condition(decimal percent, int quantity, Date.
Time dt){}public bool Calculate(){// long calculation of some condition}}Замещение алгоритма (замените алгоритм на более понятный). Оптимизация кода для лучшей читаемости и/или производительности. Fromstring Found. Person(List< string> people){foreach(var person in people){if(person == "Max"){return "Max"; } else if(person == "Bill"){return "Bill"; }else if(person == "John"){return "John"; }return ""; }}Tostring Found. Person(List< string> people){var candidates = new List< string> { "Max", "Bill", "John"}; foreach(var person in people){if(candidates.
Contains(person)){return person; }}return ""; }Немного реальности и процедуре code review. Перед рефакторингом или для проверки внесенных изменения применяется процедура code review. В данном случае, речь пойдёт о «замечаниях» (критериях) review- ера. Необходимо обязательно поправить. Как правило, это очевидные вещи, которые могут приводить: к исключениям (например отсутствие проверок на null), к просадке производительности, к изменению логики работы программы. Сюда же можно отнести и архитектурные штрихи. Например если у вас весь проект написан на MVC/MVP, а новый коллега добавил форму, заколбасив всё в один файл/класс.
Чтобы не создавать прецедент и следовать правилам, конечно лучше этот спагетти- код переделать под общую архитектуру. Замечания- вопросы. Если вам, что- то не понятно, не стесняйтесь задавать вопросы: почему именно такое решение, почему выбран такой алгоритм, зачем такие навороты. Вопросы полезны как для общего развития, можно освоить полезную фичу или лучше узнать текущий код. Так и для понимания того, что коллега выбрал решение осознанно.
Замечания- предложения. Тут высказываются предложения по улучшению кода, но если code commiter проигнорирует их, то я не буду настаивать. Если же мне как code commiter- у что- то предлагают, я чаще стараюсь сделать это.
Тут я исхожу из того соображения, что review- ер это преподаватель, который проверяет код и он прав, конечно если предложения не доходит до абсурда. Что- то предлагая, можно это аргументировать кодом для наглядности. Реальность такова, что грань между этими критериями может быть разная для каждого программиста, но это терпимо — нормально. Хуже когда у review- ера отсутствует 3- й критерий, т. Становясь уже code commiter- ом он наоборот, только и применяет 3- ий критерий.
А когда сталкиваются два таких человека, это флейм, крики (видел и с матерком ). Чтобы разрешить конфликт, нужна 3 сила, как правило другой программист (желательно с большим опытом) должен высказать своё мнение. Про конфликты интересов и их решения расскажу в следующей статье.