Тёмный

Цикломатическая сложность кода. Как её снизить? 

easydev
Подписаться 4,7 тыс.
Просмотров 11 тыс.
50% 1

Опубликовано:

 

31 окт 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 81   
@happy_cutman
@happy_cutman 11 дней назад
Спасибо большое за видео, особенно, за два последних концепта, поддержите автора, человек бесплатно делает очень полезный контент
@АлександрКнязев-ю1в
Классно, приятно слушать человека который сам понимает то, что говорит👍Спасибо!
@easydev1205
@easydev1205 2 дня назад
Спасибо, за добрые слова!
@88coolv
@88coolv 3 дня назад
1. цикломатическая сложность определена только для структурных программ. Если в программе есть хоть что-то из: ФВП, виртуальные вызовы, указатели на функции, вычисляемые переходы и т.п. конструкции, то цикломатическая сложность становится неопределенной. Поэтому невозможно снизить цикломатическую сложность при помощи всяких filter/reduce, полиморфизма и других таких вещей. 2. цикломатическая сложность от использования ранних возвратов не уменьшается, а растет. Поэтому практически всегда ранние возвраты не рекомендуются - они существенно снижают читабельность кода и усложняют его поддержку. 3. Использование хештаблиц и любых других подобных подходов, естественно, ни как не снижает цикломатическую сложность.
@easydev1205
@easydev1205 3 дня назад
Приняли. Будем иметь в виду.
@gi9ex70
@gi9ex70 11 дней назад
Дружище, огромное спасибо за видеоролик. Очень информативно и интересно. Продолжай в том же духе) Жду следующего видева
@thats_embarrassing_JS
@thats_embarrassing_JS 9 дней назад
Очень классное видео, которое будет полезным для начинающих. Автор красава. Единственный недочёт - последний пример не является реализацией паттерна Состояние. Данный паттерн предполагает, что состояние объекта может меняться. Логика изменения состояние описывается либо в классе, реализующий конкретное состояние, либо же в основном классе, в котором состояние меняется. А данный пример корректней было бы назвать реализацией паттерна Стратегия, только вместо функции, которая требует, чтобы класс реализовывал конкретный интерфейс(в нашем случае, классы наследуются от абстрактного класса ShapeState), используется класс Shape.
@easydev1205
@easydev1205 2 дня назад
Спасибо!
@serb1146
@serb1146 2 дня назад
Пример с фигурами лучше было использовать для объяснения полиморфизма подтипов! Многоформенность! Формы фигур же! А вот способ доставки можно было использовать для State pattern, за исключением что там еще добавлен static Factory method (зачем?). С Value Object - придется вам перечитать теорию снова, и обратить внимание на слово equality и задуматься почему это так важно. Лайк, однозначно!
@easydev1205
@easydev1205 2 дня назад
Спасибо! И почему же важно?
@shvedovdanil
@shvedovdanil 5 дней назад
Есть легенда, что светлые программисты для замены цепочки if придумали switch, но перешедшие на тёмную сторону тимлиды стали распространять грязные слухи о безвкусии переключателя и о нём уже мало кто помнит. Я же скажу "Switch жив!"
@easydev1205
@easydev1205 5 дней назад
Тоже верно. В определённых ситуациях switch вполне хорош
@ПавелФомин-ъ4с
@ПавелФомин-ъ4с 5 дней назад
switch хорош только до тех пор, пока возможно его применить. и кто сказал, что switch не является ветвлением? разница какая? 😊
@ПавелФомин-ъ4с
@ПавелФомин-ъ4с 5 дней назад
а вообще конечно стейты рулят 😅
@shvedovdanil
@shvedovdanil 5 дней назад
@@ПавелФомин-ъ4с Все инструменты хороши, пока их можно применить. Никогда не видел код, который был бы хорош там, где его невозможно применить. В видео автор не избавлялся от ветвления, а делал его более читабельным для человека и более рациональным. Про return из разных мест рассказал, а вот про continue и break в циклах не стал упоменать.
@БоряДикий
@БоряДикий 4 дня назад
В питоне лучше словарь юзать
@geoffreycollins6627
@geoffreycollins6627 Час назад
Спасибо за видео. в блоке с полиморфизмом/стратегией мне не понятно вот что: в изначальной "плохой" реализации сущность сообщения у нас объект, что заставляет думать, что мы изначально не знаем, какой тип сообщения мы должны отослать, поэтому и пишем условия внутри функции. а во второй "правильной" реализации мы как будто уже знаем, какой тип сообщения хотим отослать, "оборачивая" строку нужным классом. Но как быть все-таки если мы не знаем тип сообщения заранее? Например, если нам пришел ответ с вот таким объектом, как в изначальном примере, и исходя из того, что у него внутри, нужно выбрать необходимую стратегию отсылки? Получается, опять те же if-ы использовать?
@AlekseiBleile
@AlekseiBleile 16 часов назад
только хотел сказать что где же она чистая если у нее руки в 26 строке испачканы, а ты сам подправил. люблю когда возникает замечание, а автор сам тут же отвечает. как будто интерактив)0
@МирославМилаев
@МирославМилаев 11 дней назад
Спасибо! Оказывается паттерны в JS можно применять чаще чем кажется )
@tontontonic
@tontontonic 11 дней назад
последний пример я чет не особо и понял) например в первом варианте, где внутри класса иф-елсе в зависимости от передаваемого типа - так я могу например массив типов запустить в цикле и получить нужные значения, так как все ветвления в классе в решении же мне нужно создать класс под каждый тип и все равно нужно понимать какого класса передо мной объект, чтоб получить нужное значение типа в первом варианте я могу сделать так let result = {} types.forEach(type=>{ result[type] = new Shape(type) })// let a = result.circle.draw() ну или что то подобное во втором же мне придется делать то же самое ветвление, только не внутри класса, а уже внутри цикла, типа (if type == 'circle') result[type] = new Shape(new CircleState()) то есть ветвление ни куда не делось, а просто переходит на уровень выше?) и кода больше, мне как-то не ясна выгода хотя скорее всего я просто что-то не понял)
@user-alzKfArQ8
@user-alzKfArQ8 5 дней назад
Сказки для самых маленьких. Есть сложность предметной области. Если к примеру у вас 3 типа договоров и 3 типа клиентов, то рано или поздно эти типы и связи между ними будут где-то фигурировать. Или в программе вы их внесете или в базу данных или в текстовый файл. Но есть принципиальные вещи, которые делают программу дурако-устойчивой или неустойчивой. Например если программист пишет if( type==1){ code1 } if( type==2){ code2 } то программа получается неустойчивой к появлению новых типов. Если админ добавит type==3, то программа посыпится с большой вероятностью. А когда кодовая база будет несколько гигабайт, то дырку найдут только через месяц, когда у какого нибудь клиента что-нибудь отвалится.
@easydev1205
@easydev1205 3 дня назад
Обозначил
@FDsagizi
@FDsagizi 5 дней назад
Да, только многие примеры будут работать сильно медленнее 😉
@easydev1205
@easydev1205 2 дня назад
Не страшно. Прямо сильно медленнее будут если там гигантские объемы данных будут. Для большинства разработчиков это неактуально
@fuad2069
@fuad2069 12 дней назад
Спасибо))
@dmitriydobrynin9528
@dmitriydobrynin9528 11 дней назад
Сам реализовывал паттерн Стратегия, чтобы рендерить ячейки сложной таблицы в зависимости от входных данных, а потому пример со Стратегией понял, естественно, легко. Но вот чем точно отличается паттерн Состояние от Стратегии вообще не осознал :( UPD: Наверное, понял. Отличается тем, что в Состоянии мы прокидываем конкретный экземпляр класса в конструктор, а в Стратегии мы ВЫЗЫВАЕМ функцию, которая дергает нужный метод у экземляра того класса, который в эту функцию прокинут. Но вообще очень похожи два эти паттерна, вот прям когда лучше один, а когда другой не понимаю. Подскажите?
@alekseyilin6605
@alekseyilin6605 10 дней назад
Паттерн Состояние достаточно специфичен, и область его применения определяется из названия. Принципиальное отличие от Стратегии заключается в том, что набор состояний и переходов между ними должны быть заранее определены, и для переходов эти состояния могут "знать" друг о друге. В данном видео это вообще никак не раскрыто. Более того, пример никакого отношения к паттерну Состояние не имеет.
@dmitriydobrynin9528
@dmitriydobrynin9528 10 дней назад
@@alekseyilin6605 примерно разобрался, спасибо. Как я понял, с вызовом метода, Состояние меняет объект от которого может вызывать дальнейшие методы определенного ранее общего интерфейса.
@nataliepodgainova6582
@nataliepodgainova6582 6 дней назад
|| "unknown command" что значит? Что на все другие команды, которых нет в ключах, будет давать результатunknown command? Что в это случае значит || ? Я думала это or, но не знала, что ее можно засунуть в print? Или я неправильно поняла?
@easydev1205
@easydev1205 4 дня назад
не понял
@nataliepodgainova6582
@nataliepodgainova6582 4 дня назад
12:22 9 строка что означает || ?
@easydev1205
@easydev1205 3 дня назад
а, ну это просто значит что если левая часть от || будет undefined то вернётся правая. Типа return commandActions[command] ? commandActions[command] : "Unknown command"; и тд по-разному можно это записать
@dgdarkking266
@dgdarkking266 3 дня назад
так погодь - так какая будет стратегия таким и будет поведение, тоже самое и у состояния
@easydev1205
@easydev1205 3 дня назад
Логично
@dgdarkking266
@dgdarkking266 3 дня назад
@@easydev1205 а в чем разница паттернов? Да и если смотреть, то фигура зависит от стратегии рисования, почему вв назвали её состоянием
@easydev1205
@easydev1205 3 дня назад
Это не я так назвал. Не я это придумал) Разница между этими двумя паттернами незначительная. По сути паттерн состояние это продолжение паттерна стратегия. О тонкостях различия может сниму отдельное видео
@baileysli6235
@baileysli6235 10 дней назад
7:55 код с методами массива хуже, потому что дважды идёшь по массиву
@easydev1205
@easydev1205 10 дней назад
да, тоже верно, но наверно в 99% случаев это нестрашно
@thats_embarrassing_JS
@thats_embarrassing_JS 9 дней назад
Это некритично, если сам массив небольшой.
@rshirkhanov
@rshirkhanov 6 дней назад
Можно использовать итераторы, в таком случае обход коллекции будет единственным
@nataliepodgainova6582
@nataliepodgainova6582 6 дней назад
​@@rshirkhanovа как их использовать?
@sacinandan_kisor
@sacinandan_kisor 3 дня назад
А можно юзать reduce()
@alexperemey6046
@alexperemey6046 10 дней назад
Ты нмкак не уменьшаешь цикломатическую сложность переписыванием синтаксиса. 1) 1) Цикломатическую сложность определяется количеством тестов, которые тебе придется написать для твоего кода. Это написано в той статье, которую ты цитировал. Количество тестов, покрывающих все варианты у тебя не меняется. 2) Циклы не имеют никакого отношения к цикломатическую сложности, поскольку не создают новых вариантов выполнения.
@easydev1205
@easydev1205 10 дней назад
Спасибо за комментарий и за мнение.
@alexperemey6046
@alexperemey6046 10 дней назад
@@easydev1205 Прочти внимательно ту статью в википедии, которую ты же сам и цитировал в видео. До конца и внимательно... Вместо того, чтобы упражняться в лже-вежливости.
@easydev1205
@easydev1205 10 дней назад
Ладно, хватит хейта. Я смотрю тебя ролик задел) Заблокирую-ка я тебя наверно
@I_Deft_I
@I_Deft_I 6 дней назад
Мда, ты просто рассказал про базовые принципы ооп и ещё пару очевидных вещей. Да, видео полезно прям совсем новичкам, но не очень понятно зачем оно нужно, ведь на ютубе и так тонна подобного материала
@easydev1205
@easydev1205 6 дней назад
Все, бросаю вести канал) Ведь на ютубе тонна подобного материала
@ДенисЛюбченко-л4о
@ДенисЛюбченко-л4о 11 дней назад
3:58 что тут сложного?😂 Обычный индусский код )
@easydev1205
@easydev1205 10 дней назад
Ну это стереотип просто)
@ДенисЛюбченко-л4о
@ДенисЛюбченко-л4о 10 дней назад
@@easydev1205 я сейчас на таком проекте, код один в один. Все шутки про индусов - не шутки)
@alexperemey6046
@alexperemey6046 10 дней назад
Несколько ретернов точно так же увеличивают сложность понимания программы, как и ветвления. Поскольку они никак не уменьшают количество ветвлений, они просто записывают их в другом виде
@easydev1205
@easydev1205 10 дней назад
Спасибо за комментарий и за мнение. Да, на понимание кода паттерны тоже конечно влияют. Нужно использовать разумно
@alexperemey6046
@alexperemey6046 10 дней назад
@@easydev1205 Не паттерны, return...
@AndroidsReview
@AndroidsReview 10 дней назад
Это делает код более плоским
@КириллЧе-я5ы
@КириллЧе-я5ы 7 дней назад
Не согласен. Поскольку эти ветвления выглядят как слои а не граф. Вы проходите сквозь текст спокойно отсеивая условия а не пытаясь понять логику ветвления.. Например, это очень хорошо использовать при вводе различных данных и их валидации
@TheBypasser
@TheBypasser 3 дня назад
"Что, соответственно, минус" - ну и тут я уже слушать и перестал: во-первых, ну главное-то в коде всё ж не примитивность, а оптимальность, и - во-вторых - всё равно автомат на кучу состояний читаем куда лучше пятка раскиданных по коду IFов. Разбить функцию на кучу мелких - можно, конечно, заинлайнить пару-тройку совсем уж логически отвязанных от остального кода вещей (что нечасто и имеется) - но скорее всего у тебя просто получится убогое опенсорсное спагетти. Помните, дети: функции, классы и т.п. сделаны для того, чтобы применяться в разных частях программы по многу раз, и правя любую подобную штуку, редактирующий будет всё время отвлекаться на то, что же эта правка затронет - и всё ради того, чтоб увидеть (желательно, вообще в другом файле), что функция эта - очередной такой вот изврат. Едем дальше. Твоё "функциональное программирование" вообще к функциональному программированию отношения не имеет, вот совсем и никак. Почему ж вы все обычные процедуры обзываете "функциональным программированием" ?.. А так - да тут половина примеров была б нормальными, если б уже все поняли, что скобки после кондишнов надо на новую строчку переносить (тогда сразу видно, скоуп там, или просто одиночный вызов), и всякой чуши типа return; else не писали... Или (я просто на скриптах не писал давно) в отличае от нормальных C/С++, тут IF без скобок не работает?
@easydev1205
@easydev1205 2 дня назад
Ничего не понятно, но очень интересно) Спасибо за комментарий
@andreysemykin5879
@andreysemykin5879 7 дней назад
"Ранний выход" это дерьмо собачье, нарушение правила дейкстры. Если у вас слишком много в одном методы, вы должны делить метод.
@easydev1205
@easydev1205 7 дней назад
Приняли. Будем иметь в виду.
@LibertyOrGirl
@LibertyOrGirl 5 дней назад
@@easydev1205 Человек выразился не очень красиво и корректно, но в целом он прав. Функции с несколькими return ещё сложнее поддерживать и отлаживать, чем функции с многими if-else. Иначе говоря, Вы предложили избавляться от плохого подхода с помощью ещё более плохого подхода.
@easydev1205
@easydev1205 5 дней назад
Мнение имеет место быть. Я с ним скорее не согласен. Я не считаю ранний выход плохим подходом.
@andreysemykin5879
@andreysemykin5879 5 дней назад
@@easydev1205 да считайте что угодно, но вы вряд ли потянете с ваши мнением на ученого-математика в области информатики и тому подобное, кому-то знаете ли и goto написать не зазорно. Советую ознакомиться с термином структурное программирование. А по поводу ранних выходов, если метод грубо говоря в десяток строк умещается, это еще терпимо, но многие их лепят черти знает как на несколько экранов, поэтому чем строже правила, тнм чище резкльтат в общем случае. И кстати return не в конце метода это тоже разновидность goto
@easydev1205
@easydev1205 5 дней назад
Так вы то на моём канале) и во всех видео исключительно мое мнение. Я не считаю ранний выход плохой практикой - поэтому так и говорю в видео.
@DaB00gieW00gie
@DaB00gieW00gie 3 дня назад
к тернарному оператору и конкретному примеру с голосованием напрашивается такое: let age = 18 let canvote = age >= 18 && true console.log(canvote) не обзывайтесь только!
@easydev1205
@easydev1205 2 дня назад
Слишком замудрёно
@DaB00gieW00gie
@DaB00gieW00gie 2 дня назад
@@easydev1205 а что тут мудрого? вместо тернарного оператора тут простое логическое "и" - всегда возвращает или true или false, это удобнее, если тебе эти [yes,no] нужны не на вывод, а для дальнейшего использования.
@easydev1205
@easydev1205 2 дня назад
Да, просто для такой простой логики должно быть каждому разработчику с первого взгляда понятно как это работает. Если это кого-то заставит призадуматься - я откажусь от такого решения. Это именно у меня такой подход. По крайней мере стараюсь так делать. Поэтому я, например, в своём коде такого точно использовать не буду. А там каждый сам решает
@DaB00gieW00gie
@DaB00gieW00gie 2 дня назад
@@easydev1205 т.е. не все разработчики знают как работает "&&" и для чего нужен булев тип данных? в JS (да и в других языках) ведь очень много всего, что возвращает true или false. это простая, понятная и универсальная штука. разве нет?
Далее
Voy shetga man aralashay | Million jamoasi
00:56
Просмотров 932 тыс.
ХУДШИЕ ВЫБОРЫ в США
13:20
Просмотров 570 тыс.
Как Linux рисует окна?
48:46
Просмотров 48 тыс.
КАК УСТРОЕН TCP/IP?
31:32
Просмотров 196 тыс.