Что такое code smells и его устранение
Вставка
- Опубліковано 4 чер 2024
- Вы просили - мы сделали! Вот видео о том, что такое code smells, типичные признаки и устранение code smells. Приятного просмотра ☕ 👀
Підписуйтесь на наш україномовний канал - www.youtube.com/ @SerhiiNemchynskyi
Видео о которых говорит Сергей:
• Исправляем очень плохо...
• Что делать, если твой ...
• Программист, ты должен...
Плейлист по Clean Code - • Clean Code (Как помыть...
🧠 Регистрируйся прямо сейчас на менторинг
⬇️ Учись у профи ⬇️
🦊 Менторинг:
JAVA - go.foxminded.ua/48Yksss
PYTHON - go.foxminded.ua/3SFZBV6
C#/.NET - go.foxminded.ua/42ooRlQ
ANDROID - go.foxminded.ua/3w0VNVs
FRONT-END (ANGULAR, REACT) - go.foxminded.ua/3SIyeJV
SALESFORCE Developer - go.foxminded.ua/3SrZ87F
UI/UX дизайн - go.foxminded.ua/3OsP64X
Unreal Engine - go.foxminded.ua/3ukmt2Z
QA Automation - go.foxminded.ua/48WuuKI
IOS разработка - go.foxminded.ua/49nzkAx
PHP - go.foxminded.ua/3HJHLKv
Unity - go.foxminded.ua/3UpWKkl
NODE.JS - go.foxminded.ua/3Uraewm
GOLANG - go.foxminded.ua/48ZBPcb
Обучение на проекте - go.foxminded.ua/47Z8Q79
🦊 Стартовые курсы для новичков (Java Start, Java Tools, Python Start, C++ Start, C# Start, JS Start) - go.foxminded.ua/3Opr5M4
🦊 Продвинутые курсы для состоявшихся девелоперов:
Enterprise patterns - go.foxminded.ua/3Sn74ae
GRASP and GoF Design patterns - go.foxminded.ua/4bjd38H
Алгоритмы и структуры данных - go.foxminded.ua/490d27U
C# NEXT - go.foxminded.ua/491rEnM
🔧 Пробное техническое собеседование со специалистом уровня Senior Developer/ Team Leader - go.foxminded.ua/3HM7wdf
👔 Карьерная консультация с Сергеем Немчинским - go.foxminded.ua/3vXdULT
Есть вопросы по обучению в FoxmindEd? Пишите нам в телеграм - t.me/foxminded
Вы можете стать спонсором канала и получать плюшки - / @sergeynemchinskiy
❤ FoxmindEd в Instagram: / foxminded.ua
Новый поток авторского тренинга Сергея Немчинского стартует уже 01.02.2024
Сайт FoxmindEd для новичков: go.foxminded.ua/4bn81b3
Сайт для разработчиков уровня мидл+: go.foxminded.ua/4bepank
FoxmindEd в ФБ: / foxmindedco
FoxmindEd в Instagram: / foxminded.ua
Мой Telegram: t.me/nemchinskiyOnBusiness
Для деловых запросов: youtube@foxminded.ua
Тайминг:
00:00 - Вступление Сергея Немчинского
00:42 - Что такое Code Smells
02:02 - Типичные примеры code smells включают
06:51 - Менторинг
07:36 - длинные методы
09:03 - длинный список параметров
11:35 - комментарии
12:44 - ненужные примитивные переменные
13:42 - сгустки данных
16:35 - Что вызывает code smells
17:40 - Устранение code smells с помощью рефакторинга
#nemchinskiy #рефакторинг #codesmells
Сижу вырезаю тонны древних комментов из кода и тут такое видео😂 Спасибо ❤
"ненужные" примитивные переменные, на самом деле это не плохой код. Они нужны чтобы "обозвать" промежуточные данные, чтобы сократить длину строк кода, где есть вложенные вызовы, а так же чтобы смотреть их значение в дебаггере.
Плюс код стає зрозумілішим. Коли ти запихуєш в цю змінну результат виконання методу, одразу бачиш тип даних, що вертає метод, а також назва змінної вже каже, що, куди і навіщо
Абсолютно согласен. Может быть с запашком, только в случае если метод очень-очень простой
Надо стрим запилить. Открыть какой-нибудь проект и на прямом примере показать где плохо, а где хорошо)
очень в тему. спасибо, сергей!
Интересно и познавательно. Спасибо, Сергей и команда Foxminded!
13:01 Тут вообще мимо. Делать переменные что бы получить результат функции и передать дальше - абсолютно нормально, и как раз таки по рукам нужно бить когда пишут вот так: send_to_server(get_sensor_value()). Во-первых, используя переменную, удобнее читать код, потому что если это будет функция, параметр которой вызов другой функции, у которой параметр вызов ещё одной функции- это тихий ужас. Во-вторых, возможно результат нужно будет потом где-то использовать, и не нужно будет переносить туда сюда вызов функции. Ну и самое главное: Дебаг. Дебажить код, где результат каждого вызова находится в своей переменной - намного проще, ибо как узнать результат функции, значение которой передаётся сразу в другую - непонятно. Разве что в некоторых дебаггерах можно прямо в дебаггере вызвать функцию, но это такое себе, ибо не факт что результат будет таким же
Ага, особенно когда таких вызовов много. Читабельность ниже плинтуса.
return getSome(getSomethingElse().getAnotherSome(new HereWeGoAgain(name, code)), getThisOneToo());
Я стараюсь избегать использование вызова метода в качестве параметра, только в простых случаях. А когда в одной строке вызовов методов 3 и больше - код может тяжело читаться. С другой стороны имя промежуточной переменной может помочь в понимании кода.
Совершенно верно, и брейкпоинт поставить на промежуточную переменную - тоже удобно. Как говорит один известный IT-блоггер: любой дурак может написать код, понятный компьютеру. Хороший программист пишет код, понятный человеку
скажем так, лично я не ставлю себе рамок и пишу и так, и эдак в зависимости от "интуитивной необходимости". И да, это единственный аспект в видео, с которым я в чём-то не согласен
Очень понравилось про закоментированный код, слушал и удалял)
Отвлекся на минуточку пост тиснуть и сейчас же продолжу.
Спасибо, Сергей и твоя команда!
Сергей и весь коллектив канала, традиционное спасибо за выпуск, как всегда здорово - интересно и содержательно 🙏
помню я все таки писал комменты в коде. алгоритм был сложноватый и гдето с 3-й строчки у меня самого дымок из ушей шел и я просто даже для себя написал что вот тут я удаляю то-то для тогото и в другом месте тоже чтото написал. Синьоры которые обычно любили клевать на ревью на эти комменты не делали замечания, ну там реально сложно было понять просто читая код, ну и в итоге работал он быстро
Спасибо за видео Сергей, классная кофта)
Прекрасное видео ещё одна хорошая книга в копилку. Спасибо Сергей пойду читать. А на счёт тренинга да хотим и курс по java тоже а что нет)
Спасибо за рекомендацию по поводу книги по рефакторингу.
Получается вчера на стриме был "индус" со своими case'ми :)
меня кстати реально бесит закомментаренный код. типа, там ещё сверху написано "не трогать, оно будет надо тогда-то" причём, оно надо тогда-то уже больше года. я всегда в PR делаю пунктик в конце: "а ещё я удалил из такого-то файла 150 строк кода, который делал ничего". и всёравно мне кидают в PR комментарии "зачем ты убрал - оно будет надо".
"Ненужные переменные", которые сразу после получения передаются, делают для целей отладки, когда нужно понять, что именно возвращает метод. В релизном коде оптимизатор, скорее всего уберет эту переменную.
да причём тут релиз. Любой "запашок кода" - это для программиста, компилятору вообще пофиг по большому счёту, как код написан, если он выполняет тоже самое. Ненужные переменные усложняют чтение и понимание, по ним непонятно, участвуют они вообще в процессе, влияют на что-то или нет
Во всех современных языках давно есть передача параметров по названию
Ура, новое видео!
Большое спасибо за то, что делитесь знаниями, Сергей! Но вот про свич всё-таки некоторые опытные программисты говорят, что он не так уж и плох.
Конечно же хотелось бы ваш рассказ про рефакторинг :) Читать влом))
"свитч не так уж и плох" может быть только для совсем примитивных вещей, когда, например, записать разные строки в зависимости от значения в какой-нибудь условный лог (и не более) проще, нежели городить и внедрять ещё одну сущность и только в том месте, которая гарантированно будет всегда простой как двери и не требующей тестирования. Тогда, может быть, допускается этот свитч (и то, я не сторонник его, потому как иногда даже совсем простые вещи начинают разрастаться, требуют изменения в старый код и провоцируют регрессивное тестирование)
Спасибо большое за Ваши видео.
Прокомментируйте пожалуйста Apple Vision Pro, какие перспективы Вы видите, какой язык понадобится для разработки приложений под Vision Pro. Спасибо !
перспективно. Свифт
Не хватает усидчивости самому читать книгу по рефакторингу, сделайте пожалуйста видеооо, все 10 часов 3 раза пересмотрю)
Здравствуйте , можете пожалуйста обьяснить на простых словах про DOM JS ? Спасибо
Бывает код, покрытый тестами, а у меня - код, порытый туду-шками :)
Интересен тренинг по рефакторингу))
я программист-любитель. но когда мне нужны были просто координаты - я создал класс с переменными X, Y и сеттерами/геттерами. мне это показалось очевидным! сам додумался! ))
"одноразовые переменные" использую при отладке, если получаемый объект зависит от времени, или сложно конструировать.
Эх, Сергея Немчинского больше не зовут «всё ещё Сергей Немчинский»
((
Ушла эпоха
Да я так хотел зарефакторить крафт и готовку. В общем всё вроде нормально объединил, но суть до дела полается нужны другие переменные чтобы показать отличия. Код становится непонятной лапшой. Вывод лучше пусть код повторяется, чем он становится непонятным с первого взгляда
Так буде цікавим. Можливо буде наступним після GRASP and GOF
Сергей что Вы думаете о книге Khalila Stemmlera
The Software Design & Architecture Handbook?
Раньше, когда я что-то переделывал в коде, то заодно сразу рефакторил и закомменченые части - и даже так они мне ни разу не пригодились =D С тех пор, как это заметил, удаляю их без тени сомнения
Вопрос: Если я учусь по видео и делаю по ним проекты, смотрю, что делает автор, и повторяю за ним, и так делаю сайты, это копипастинг? Стоит так делать, или лучше делать самому? Спасибо заранее!
Это нормально для начала учебы, но уже пора начинать делать все самому
хорошее видео
За тренинг по рефакторингу двумя руками
К многим из приведенным здесь советам я допер сам методом проб и ошибок набивая себе шишки-это издеьржки того что я самоучка. Тише едешь дальше будешь - если не торопясь дапшь осмысленные имена переменным если не полениться и вставить коментарий - потом будет проще. Еще много зависит от языка - помню на бейсике была такая каша...
Если вы пишете на С то полезным будет посмотреть на то как организованы "конструкторы" структур в исходниках ядра Linux. В некоторых драйверах применяются принципы аналогичные принципам используемым в ООП, особенно в драйверах работающих с видеоподсистемой V4L2. Можно много занимательного почерпнуть
Я добавил бы следующее к code smells:
1) это создание объектов, классы которых реализуют один и тот же интерфейс, через new. Лучше использовать аннотации + рефлексия и создавать объекты в ObjectFactory
2) Использовать pojo классы, сформированные на основе json, вместо этого использовать JsonObject или String + jsonPath
Мені точно сподобався би тренінг по рефакторінгу. Та й відео на ~20 годин зайшло би. 20 годин розслабляючого голоса Сергія.... Каєф... 😅
вообще очень категорический совет и уж точно неприменимый ко всем ситуациям,
повторение (копирование) кода вполне нормально к тем местам, где мы уверенны что логика будет другой, в тех же местах где нам надо чтобы логика была той же, но обьекты другими, надо переделывать под дженерики а не копировать
если у вас есть похожая, но не точно такая же логика, то это повод вычленить из неё идентичные участки, создать базовый (скорее всего, абстрактный) класс, реализующей эти участки (хотя в последней версии шарпа можно и в интерфейсах писать логику :) ) и в классах-наследниках уже реализовать различия, реализовав соответствующие абстрактные методы, а не городить 2 похожих кода в разных местах
9:05 Я как-то раз дебажил код, в котором один метод отвечал за сразу за чтение, создание, обновление и удаление (!!!) сущностей, в зависимости от набора параметров. Вишенкой на торте было то, что метод, к тому же, вызывался из десятков разных мест. И нет, там не было просто параметра типа action, туда передавалось с десяток разных параметров и всё это иффалось по - "пойди разбери какой" логике. Сам баг заключался в том, что при открытии определённой страницы из базы пропадали данные(кто бы мог подумать...). Естественно я не стал продолжать эту вакханалию, не стал просто подбирать параметры, а разделил все эти функции по своим методам. Тут и список параметров резко сократился. Надеюсь у автора этого кода уши горели, пока я этот клубок распутывал.
Тренинг по рефакторингу интересен!
Не могли вы снять видео что должен знать джуниор с++
Даешь тренинг по рефакторингу! ))
Коли вкотре чую що метод повинен буту не більше строрінки, так і хочу показати це відіо своєму шефу. В мене на фірмі код в 1000 строк це норма, максімально здається десь біля 2000 . Колі я почінаю працювати с новим для мене методом, пару годин може знадобитись щоб зрозуміти як це працює.
Я бы еще к плохому коду отнес лишком длинные классы
А где Сергей Немчинский? Он вернётся?
Та самая тонкая грань, между дублированием кода и принципа SRP, как понимать когда нужно реюзнуть уже имеющийся код, а когда нужно написать похожий код, но использующийся в другом месте с похожей, но не точно такой же логикой.
если у вас есть похожая, но не точно такая же логика, то это повод вычленить из неё идентичные участки, создать базовый (скорее всего, абстрактный) класс, реализующей эти участки (хотя в последней версии шарпа можно и в интерфейсах писать логику :) ) и в классах-наследниках уже реализовать различия, реализовав соответствующие абстрактные методы, а не городить 2 похожих кода в разных местах
Я удалаю тоже, даже не принимаю такой код )))
Да уж, индусы нынче switch-case'ом пишут)
На счет мертвого кода, который никто не юзает. Если не ошибаюсь, то компилятор детектит такие куски кода и выкидывает их
Дело не в компиляторах, а в том что человеку не удобно.
Про "закомментированный" код улыбнуло. Каждая нормальная IDE поддерживает сворачивание блоков кода любого размера, так что это точно не должно являтся проблемой. Также иногда бывает полезным оставлять такие блоки, чтобы в дальнейшем понимать, как возникла новая версия этого блока. Например, какой-то сложный алгоритм, который был изначально реализован в каком-то методе, потом этот метод был существенно переделан, но без старой версии этого метода трудно понять(если вобще возможно), почему именно так в последствии был реализован алгоритм в данном методе.
Если новая версия без старой не читается - то, скорее всего, у вас не очень хорошо реализована новая версия. Это скорее повод для рефакторинга, а не повод оставления старого и, скорее всего, уже неработающего кода. Если понять всё равно тяжело - значит, у вас метод взял на себя слишком много, дробите его.
Резюмируя: желание оставить старый код прежде всего говорит о проблемах в новом коде
Ещё бы к запахам кода отнёс void метод get, который что-то изменяет, и метод set который возвращает какое-то измененное значение, и их комбинация когда пропускают промежуточные переменные и в аргументы метода get передают возвращаемое значение метода set 😂 и это не придумано, а описание случая из жизни
да ну нахер :) остановите землю, я сойду
@@SergeyNemchinskiy земля в безопасности - было переписано, ускорено и сейчас только история гита хранит упоминание об этом
у вас уже прям какие-то извращения.... 😀
@@oshastitko доводилось переделывать плохо пахнущий (и работающий) код. В одном случае был труд индийской студии и там транзакция в БД ждала ответа платежного сервиса :D
Даешь тенинг
"12:44 - ненужные примитивные переменные" - вот не согласен. есть еще простота и читаемость кода. если будет метод, и в этом при вызове метода для передачи значений вызываются еще методы, несколько, - то можно глазки сломать. пример foo(foo1(value1, value2), foo2(value1), foo3(value1, value2, value3)); 👀. уф... если спуститься на уровень ниже - то все равно создается область в памяти, которая содержит результат выполнения метода и затем передается в метод. если создать переменную для сета в метод - то эта переменная будет указывать на результат выполнения метода и затем этот результат будет передан методу который нуждается в этой переменной. в таком случае читаемость кода возрастает в разы. в итоге: не всегда нужно избавляться от переменных которые потом используются в одном месте. как вариант, когда нужно избавиться - если в методе есть переменная, а потом она же возвращается значение из метода - то да, тут хорошо срезу результату делать ретурн.
я и не говорил - всегда
@@SergeyNemchinskiy да, но в контексте будто бы подразумевается 'всегда'. ще раз дякую за мувік!
Ну вы даете
КАкая разница. Главно что бы программа работала и пользователи были давольны и заказчик
А там с как лучше ну это вообще мазохизм и перфекционизм
а поддержка?
"тимчасові" змінні стануть в нагоді коли ти будеш дебажить код. Замість того щоб визивати метод який повертає значення у code evaluation вікні, ти просто стаєш на потрібний рядок дебагером та дивишся шо метод повернув, та що ти передаєш далі.
Взагалі-то будь який дебагер дозволяє подивитись результат визову метода. А ще, краще намагайтесь юзать логуванне + юніт тести заміст дебагга
вобще с такими радикальными методами без рассмотрения других вариантов это конечно же экстремизм
в чём радикализм?
Сергей, давно вы современный код не видели, особенно сеньерский. Java превратили в паскаль. Кругом инжект очередного бла-бла-бла-Service, var и перегруженные цепочки функциональщины.
да видел
Непонятно что за символ в левом верхнем углу переливается двумя цветами🤔🤔 404
копирование кода оправдано 100 если заранее известно что он будет работать отлично от исходного, и в этом случае копировние оправдано, об этом нужно сказать
Конечно, братан, всё нужно: " робить будем пока не помрём."
Как говорил один "ИЗ": " куй железо, не отходя от кассы!".
А ещё:" полян'ыца". Всё.
Не надо тренинг.
Все гораздо проще! Как сказал один великий программист: Если твой код работает корректно и выполняет свой функционал,значит - это хороший код. Все остальное второстепенно
Типичная ошибка новичка. Любой код рано или поздно ломается, или его приходится дополнять. Если новому разработчику приходится в твоём коде неделями ковыряться, чтобы разобраться, то это плохой код.
@@nicolas267s Это не мои слова, это слова программиста Маркуса Перссона.
Що за напівміри? Пахне, попахує, він смердить))
Читать книги, когда IDE все подсвечивает и подсказывает, вы серьезно?
угу
Parameter object - костыль для языков, где нет named-параметров. Надо было бы сделать на этом акцент.
Обьясни что такое named- параметры, а то не понятно о чем ты.
@@HelloWorld-ln5cy Смотри например Dart.
@@HelloWorld-ln5cy
function_name(position_param_0, position_param_1, named_param_0=default_value_0, named_param_1=default_value_1)
вызов
function_name(value_0, value_1, named_param_0=named_value_0, named_param_1=named_value_1)
начиная с 3-го именованные параметры
А так да в том же winapi функция + структура к ней на десяток параметров.
@@_dzen_tv_ а понял, это не особо решает проблемы, да код немного читаем становится, в c# есть то что вы описали, но это не особо популярный подход, куда проще вместо кучи параметров передать один обьект или структуру и не морочить голову, особенно если эти данные постоянно используются вместе, по типу векторов, проще передать структуру чем три параметра по отдельности. Автор ролика именно о таком и говорит.
@@HelloWorld-ln5cy
тут есть нюанс
get_users(UserFilter(param0=0, param1=1, ...))
против
get_users(param0=0, param1=1, ...)
Другое дело что архитектурно get_users будет расположена на слое репозиториев, а UserFilter будет определён где-нибудь в файле filters.
еще бывает оставляют, старый код закоменченным (прям огромными блоками), или вешают @Deprecated с ссылкой. на новый метод, но я сторонник удалять такое, хотя кто-то оставляет @Deprecated методы, чтобы понять, какой метод пришел на замену
В большинстве нормальных компиляторов есть tree shaking, который отбрасывает неиспользуемый код.
Как код, который никто никогда не вызывает, может приводить к ошибкам, для меня вообще загадка.
Это зависит от языка и компилятора. В си и плюсах UB в неиспользуемом коде дает право компилятору попортить, вернее неправильно соптимизировать рабочий код.
Еще как может. У меня такое было не один раз когда я начинал использовать какой-то легаси класс (который, кстати, как легаси никто не пометил(, а потом, оказывалось, что он уже давно устарел и нужно было использовать другой. А все потому, что кто-то решил, что это хорошая идея - оставить старый код в проекте
Лайт-вариант - новички могут посмотреть и решить "раз есть - значит норм", и делать похоже.
Очень просто может, хоть на этапе компиляции, это проще исправить, хоть при запуске. Например, если зависимый код был изменён. Даже если его в рантайме никто не вызывает, он может загружаться при инициализации и кидать исключения.