Всем привет! При написании кода разной сложности, у разработчиков могут быть разные подходы в зависимости от опыта и ожидаемых требований к функциональности. В случае с middle и senior кодом, код может представлять из себя применение разных алгоритмов для обеспечения максимальной безопасности пароля, подходящий для более критичных ситуаций. Но целью этого видео показать вариативность решения конкретной задачи с codewars.com. В любом случае, каждая задача требует детального изучения, для того чтобы предоставить оптимальное решение (где-то нужны спец.символы, где-то нужна функция без использования рекурсивного подхода). Спасибо за обратную связь!
Я, конечно, могу ошибаться, но, с точки зрения подкапотной алгоритмической сложности, но генерация 256-битного хеша с последующим преобразованием приведением его к base64 - это далеко не senior-ское решение, а горе от ума.
Легче взять номера символов 36-126 вместо строк с алфавитом, и работал с массивом чисел (есть разные методы для улучшения генерирования псевдослучайных чисел в заданном диапазоне) в конце переводя в строку которая является паролем
Чисто теоретически алгоритм с мидл и сеньер решениями могут работать бесконечность Хорошим решением было бы решение джуна, если в конце рандомно перемешать массив до слияния
Ахаха, дааа. Использование хэш-функции, хоть и не является алгоритмически сложным и имеет константую сложность по памяти и скорости, всё равно не самое эффективное решение. Уже после видео я понял, что лучше использовать randomBytes - встроенную функцию в модуль crypto. Она немного ускорит процесс генерации
@@whi5k3y22 это первое, что в голову пришло. А мне даже Джуна "по уровню знаний" не дают. Такие себе нынче синьоры, тухленькие. Не смог даже стандартными инструментами задачу решить - зависимостей наплодил на ровном месте
Автор видео ничего не понимает в том что он делает, самое лучшее решение тут джуновское, реальный недостаток там только один - относительно фиксированный трехсимвольный префикс, но этот недостаток очень легко убрать, нужно просто сделать случайную перестановку строки(random shuffle). А остальное мелочи, можно причесать добавить myRandomInteger от мидла, и вот это будет настоящий сеньорский код - простой, понятный и решающий задачу. "Мидловское" и "сеньерское" решение просто полное дерьмо, использовать регулярку и рекурсию для такой задачи это не показать квалификации, а показатель её отсутствия. С уважением Михаил, программист с более чем 15 летним опытом
Не знаю что хуже, в "сеньерском" решении одно плохое решение тянет другое, и в итоге получается просто буллшит бинго. Жалко людей которые заплатили за такое "обучение".
Всем привет, на связи тот самый человек из видео! Спасибо за конструктивный фидбек - что рекурсия может никогда не закончиться и код не является безопасным. Мне стало интересно, какая вероятность того, что переполнится стэк вызова из-за безвыходной рекурсии. Если интересно увидеть математическую сторону задачи, ставьте лайк под моим сообщением - выпущу видос с расчетами и объяснением
Джуновское решение самое адекватное с точки зрения оптимизации. Просто нужно доработать. Идея сначала запихнуть по одному символу из каждого словаря - очень правильная. Просто в конце нужно перемешать массив и уже объединить его в пароль.
Если мне понадобится генератор простых чисел, я просто буду брать рандомное целое число и проверять его на то, простое оно или нет. Если оно не простое, но буду буду вызывать эту функцию рекурсивно до тех пор, пока рандомное число не станет простым. Теперь я милд разработчик?
Ну да, на каждой итерации для 6-значного пароля шанс получить невалидный около 42.5%. Теперь посчитай с какой вероятностью ты не получишь пароль даже 100 раз подряд))
@@iKorewBro есть большой класс алгоритмов, называемых вероятностными. Почитай про алгоритмы Лас-Вегас, самым популярным примером которого является сортировка Хоара. Вообще-то эта сортировка при достаточном невезении работает за O(n^2), что для n > 1e6 может работать больше минуты. Почему же везде ее используют, а не ту же сортировку слиянием, которая детерминировано отрабатывает за нлог? Прежде чем писать такие комментарии пройди хотя бы базовый курс аисд..
"синйорное" решение кошмар. регулярки это ту мач, это ж не читается прям совсем. я б такое на ревью не пропустил мидловское решение топ так как его легко отмасшабировать добавлением спец симолов. в отличии от хеша чтобы удостоверится что в пароле будет 1 цифра 1 заглавная и маленькая буква достаточно просто в случайный элемент сгенерированного пароля вставить случайный элемент из lowercase digits uppercase (хотя прийдется убедится что случайно не перезапишем то что уже перезаписали 🤔). и не прийдется делать рекрсивный вызов и делать функцию проверки
тот случай когда "сеньерское" решение выглядит больше как мидловое(выглядит как можно взять кувалду(sha256) что бы забить маленький гвоздик(пароль из 20 симоволов))
В мидловском решении идет выборка случайного символа из строки, но в качестве индекса берется интервал от 0 до длины строки включительно (так настроена функция), потому может выпасть рандомно ошибка, тут как повезет. Почему все напали на регулярки - непонятно, как раз проверять через нее валидность пароля вполне нормально, а вот хеш в данном случае - ну такое себе. В целом, задача слишком простая, чтобы ее разбирать.
Сеньер - это опытный разработчик. А опытный разработчик знает, что если в задаче указано - строчные, заглавные и цифры, то за час до ввода в эксплуатацию потребуется добавить и спецсимвол. Уважаемый автор, пожалуйста, добавьте в ваше "сеньерское" решение хотя бы один спецсимвол "-*$#@_"
Мое личное мнение, что middle решение тут вообще выкинуть надо, а senior решение назвать middle, senior вряд ли будет делать это вот так, потому что здесь большой вопрос по скорости работы этой функции...
Оценка качества кода включает несколько ключевых критериев, которые помогают определить, насколько хорошо код выполняет свою задачу, легко ли его поддерживать и развивать. Вот основные из них: читаемость, поддерживаемость, производительность, надёжность. 1) Читаемость: Код должен быть простым, понятным, хорошо структурированным, самодокументируемым с понятными именами переменных. В нашем случае с этим всё обстоит не очень хорошо: неинформативные неосмысленные имена переменных; огромное количество "магических чисел", что может привести к путанице и ошибкам (и приводит!). Немного спасают комментарии. Ну, а сам код не является самодокументируемым. 2) Поддерживаемость: Код должен быть легко модифицируемым. Хорошая структура и документирование позволяют легко вносить изменения, не нарушая существующую функциональность. Остроумная идея использовать `(~~(Math.random() * 36)).toString(36)` для генерации символов приводит к уменьшению гибкости. Добавить к общему набору теперь другие символы становится не совсем простой задачей. А дублирование логики и данных (копипаст) приводит к тому, что для малейших изменений нужно вносить правки сразу в нескольких местах. 3) Производительность: Важно, чтобы код был достаточно эффективным в использовании ресурсов (памяти, процессорного времени). Избыточные вычисления или неэффективные алгоритмы могут снижать производительность. Для решения нашей задачи дополнительные обходы с map и concat являются лишними (оба метода имеют линейную сложность по времени и памяти). Заглавные буквы можно генерировать в Array.from вместе со строчными и цифрами, а добавить список обязательных символов лучше через push. Для перетасовки массива лучше использовать алгоритм Фишера-Йейтса, он даёт более равновероятное распределение элементов, при том имеет меньшую асимптотическую временную сложность по сравнению с сортировкой через sort. 4) Надёжность: код должен гарантировано выполнять свою работу и быть предсказумым. Работа нашей функции заключается в генерации случайного пароля с наличием обязательных групп символов и равновероятным выпадением всех символов в пароле в целом и на всех позициях. Тасование сортировкой уже чуть нарушает наше равновероятное распределение по позициям. Но нарушена и сама равновероятность выпадения символов. При генерации обязательных букв мы не используем 'a', 'z', 'A', 'Z' (это и есть ошибка вызванная "магическими числами" в коде), что значительно понижает их вероятность в пароле. При генерации основной части пароля мы не используем буквы верхнего регистра из-за чего повышаем вероятность выпадения цифр с 10 : 62 к 10 : 36. Таким образом, реальная вероятность для каждой из цифр в пароле (учитывая и обязательные символы) будет на 85% превышать среднюю. А по дополнительному условию задачи (хотя в тестах это не отображено) значение такого превышения не должно быть больше 50%. Вместо заключения. Код этой функции весьма любопытен, занимателен, местами остроумен, проходит имеющиеся тесты на codewars, но всё же представляет собой write-only code. При изучении JS или прохождении кат он вполне приемлем (даже более того). Но в реальных проектах лучше делать код более понятным, надёжным и поддерживаемым.
Это ж что ж за джун то такой? По моему навыки джунов недооценены. У меня 0 опыта работы в айти (ну тоесть я даже не джун) и как бы я решил как показано в последнем варианте)
Всем привет! При написании кода разной сложности, у разработчиков могут быть разные подходы в зависимости от опыта и ожидаемых требований к функциональности.
В случае с middle и senior кодом, код может представлять из себя применение разных алгоритмов для обеспечения максимальной безопасности пароля, подходящий для более критичных ситуаций.
Но целью этого видео показать вариативность решения конкретной задачи с codewars.com. В любом случае, каждая задача требует детального изучения, для того чтобы предоставить оптимальное решение (где-то нужны спец.символы, где-то нужна функция без использования рекурсивного подхода). Спасибо за обратную связь!
Я, конечно, могу ошибаться, но, с точки зрения подкапотной алгоритмической сложности, но генерация 256-битного хеша с последующим преобразованием приведением его к base64 - это далеко не senior-ское решение, а горе от ума.
Легче взять номера символов 36-126 вместо строк с алфавитом, и работал с массивом чисел (есть разные методы для улучшения генерирования псевдослучайных чисел в заданном диапазоне) в конце переводя в строку которая является паролем
Чисто теоретически алгоритм с мидл и сеньер решениями могут работать бесконечность
Хорошим решением было бы решение джуна, если в конце рандомно перемешать массив до слияния
Ахаха, дааа. Использование хэш-функции, хоть и не является алгоритмически сложным и имеет константую сложность по памяти и скорости, всё равно не самое эффективное решение. Уже после видео я понял, что лучше использовать randomBytes - встроенную функцию в модуль crypto. Она немного ускорит процесс генерации
@@whi5k3y22 это первое, что в голову пришло. А мне даже Джуна "по уровню знаний" не дают. Такие себе нынче синьоры, тухленькие. Не смог даже стандартными инструментами задачу решить - зависимостей наплодил на ровном месте
Автор видео ничего не понимает в том что он делает, самое лучшее решение тут джуновское, реальный недостаток там только один - относительно фиксированный трехсимвольный префикс, но этот недостаток очень легко убрать, нужно просто сделать случайную перестановку строки(random shuffle). А остальное мелочи, можно причесать добавить myRandomInteger от мидла, и вот это будет настоящий сеньорский код - простой, понятный и решающий задачу.
"Мидловское" и "сеньерское" решение просто полное дерьмо, использовать регулярку и рекурсию для такой задачи это не показать квалификации, а показатель её отсутствия.
С уважением Михаил, программист с более чем 15 летним опытом
Регулярка еще ладно, но вот рекурсия в такой задаче прям очень не очень.
Не знаю что хуже, в "сеньерском" решении одно плохое решение тянет другое, и в итоге получается просто буллшит бинго. Жалко людей которые заплатили за такое "обучение".
Я зашёл чтобы оставить такой же комментарий. Но раз он уже есть, то спасибо @misha9446
Спасибо, Михаил! Очень конструктивно и по делу. Скоро выйдет ещё одно видео с тремя способами решения - буду ждать от Вас очередного фидбека! 🙌
Всем привет, на связи тот самый человек из видео!
Спасибо за конструктивный фидбек - что рекурсия может никогда не закончиться и код не является безопасным.
Мне стало интересно, какая вероятность того, что переполнится стэк вызова из-за безвыходной рекурсии. Если интересно увидеть математическую сторону задачи, ставьте лайк под моим сообщением - выпущу видос с расчетами и объяснением
Джуновское решение самое адекватное с точки зрения оптимизации. Просто нужно доработать.
Идея сначала запихнуть по одному символу из каждого словаря - очень правильная. Просто в конце нужно перемешать массив и уже объединить его в пароль.
"На Синьорское решение у меня ушло больше времени, " - я то думал, что суть Синьора в обратном - получать тот же результат за меньшее время.
04:21 почему выбираем из lowerCase от 0 до 28, если в английском алфавите всего 26 букв ? Одинарные ковычки ( ' ' ) тоже входят в вычисление ?
Тоже в шоке
И как он тест прошел?
не входят кавычки) let str = 'abcdefghijklmnopqrstuvwxyz'; str.length; // 26
Если мне понадобится генератор простых чисел, я просто буду брать рандомное целое число и проверять его на то, простое оно или нет. Если оно не простое, но буду буду вызывать эту функцию рекурсивно до тех пор, пока рандомное число не станет простым. Теперь я милд разработчик?
Если сможете вовремя выйти из рекурсии, то да )))
Ахаха, получается так 😂
отличное мидловское решение с потенциально бесконечным временем выполнения :))
Ну да, на каждой итерации для 6-значного пароля шанс получить невалидный около 42.5%. Теперь посчитай с какой вероятностью ты не получишь пароль даже 100 раз подряд))
@@aertyty3900 какая разница какой шанс, тут главное что он не нулевой. А должен быть нулевой иначе твой код - говно
@@iKorewBro есть большой класс алгоритмов, называемых вероятностными. Почитай про алгоритмы Лас-Вегас, самым популярным примером которого является сортировка Хоара. Вообще-то эта сортировка при достаточном невезении работает за O(n^2), что для n > 1e6 может работать больше минуты. Почему же везде ее используют, а не ту же сортировку слиянием, которая детерминировано отрабатывает за нлог? Прежде чем писать такие комментарии пройди хотя бы базовый курс аисд..
"синйорное" решение кошмар. регулярки это ту мач, это ж не читается прям совсем. я б такое на ревью не пропустил
мидловское решение топ так как его легко отмасшабировать добавлением спец симолов. в отличии от хеша
чтобы удостоверится что в пароле будет 1 цифра 1 заглавная и маленькая буква достаточно просто в случайный элемент сгенерированного пароля вставить случайный элемент из lowercase digits uppercase (хотя прийдется убедится что случайно не перезапишем то что уже перезаписали 🤔). и не прийдется делать рекрсивный вызов и делать функцию проверки
А модуль crypto это не из node js? По условиям задачи мы можем использовать модули из node js? Или только чистый js?
Очень полезное видео, спасибо большое за твой труд. Это мое первое видео на твоем канале
тот случай когда "сеньерское" решение выглядит больше как мидловое(выглядит как можно взять кувалду(sha256) что бы забить маленький гвоздик(пароль из 20 симоволов))
Формат супер, можно записывать и другие задачи
Услышали 😄 Будем снимать дальше!
Не заметил, что на последнем решении VSCode слишком мелкий. В следующий раз увеличу масштаб👌
В мидловском решении идет выборка случайного символа из строки, но в качестве индекса берется интервал от 0 до длины строки включительно (так настроена функция), потому может выпасть рандомно ошибка, тут как повезет. Почему все напали на регулярки - непонятно, как раз проверять через нее валидность пароля вполне нормально, а вот хеш в данном случае - ну такое себе. В целом, задача слишком простая, чтобы ее разбирать.
Сеньер - это опытный разработчик. А опытный разработчик знает, что если в задаче указано - строчные, заглавные и цифры, то за час до ввода в эксплуатацию потребуется добавить и спецсимвол. Уважаемый автор, пожалуйста, добавьте в ваше "сеньерское" решение хотя бы один спецсимвол "-*$#@_"
Можно же напрямую использовать base62 из библиотеки bases
Как так же форматировать код как на 17:58?
Prettier
Мое личное мнение, что middle решение тут вообще выкинуть надо, а senior решение назвать middle, senior вряд ли будет делать это вот так, потому что здесь большой вопрос по скорости работы этой функции...
Интересное видео, и комментарии
Вот мой вариант решения, буду рад комментариям )):
function generator(){
// Создаем массив с тремя обязательными символами
let arr = [
((~~(Math.random() * (36 - 12))) + 11).toString(36), // случайная строчная буква
((~~(Math.random() * (36 - 12))) + 11).toString(36).toUpperCase(), // случайная заглавная буква
(~~(Math.random() * 10)) // случайная цифра
]
let arr2 = Array.from({ length: 3 + (~~(Math.random() * 15)) }, (_,i)=>(~~(Math.random() * 36)).toString(36)); // создаем массив - случайные буквы и цифры от 3 до 17
arr2 = arr2.map((elm) => (~~(Math.random() * 2)) ? elm.toUpperCase() : elm) // случайно делаем некоторые буквы заглавными (не обязательно)
let str = arr.concat(arr2).sort(() => Math.random() - 0.5).join(''); // Объединяем массивы, перемешиваем (не обязательно), объединяем в строку
return str;
}
Оценка качества кода включает несколько ключевых критериев, которые помогают определить, насколько хорошо код выполняет свою задачу, легко ли его поддерживать и развивать. Вот основные из них: читаемость, поддерживаемость, производительность, надёжность.
1) Читаемость: Код должен быть простым, понятным, хорошо структурированным, самодокументируемым с понятными именами переменных.
В нашем случае с этим всё обстоит не очень хорошо: неинформативные неосмысленные имена переменных; огромное количество "магических чисел", что может привести к путанице и ошибкам (и приводит!). Немного спасают комментарии. Ну, а сам код не является самодокументируемым.
2) Поддерживаемость: Код должен быть легко модифицируемым. Хорошая структура и документирование позволяют легко вносить изменения, не нарушая существующую функциональность.
Остроумная идея использовать `(~~(Math.random() * 36)).toString(36)` для генерации символов приводит к уменьшению гибкости. Добавить к общему набору теперь другие символы становится не совсем простой задачей.
А дублирование логики и данных (копипаст) приводит к тому, что для малейших изменений нужно вносить правки сразу в нескольких местах.
3) Производительность: Важно, чтобы код был достаточно эффективным в использовании ресурсов (памяти, процессорного времени). Избыточные вычисления или неэффективные алгоритмы могут снижать производительность.
Для решения нашей задачи дополнительные обходы с map и concat являются лишними (оба метода имеют линейную сложность по времени и памяти). Заглавные буквы можно генерировать в Array.from вместе со строчными и цифрами, а добавить список обязательных символов лучше через push.
Для перетасовки массива лучше использовать алгоритм Фишера-Йейтса, он даёт более равновероятное распределение элементов, при том имеет меньшую асимптотическую временную сложность по сравнению с сортировкой через sort.
4) Надёжность: код должен гарантировано выполнять свою работу и быть предсказумым.
Работа нашей функции заключается в генерации случайного пароля с наличием обязательных групп символов и равновероятным выпадением всех символов в пароле в целом и на всех позициях.
Тасование сортировкой уже чуть нарушает наше равновероятное распределение по позициям. Но нарушена и сама равновероятность выпадения символов. При генерации обязательных букв мы не используем 'a', 'z', 'A', 'Z' (это и есть ошибка вызванная "магическими числами" в коде), что значительно понижает их вероятность в пароле. При генерации основной части пароля мы не используем буквы верхнего регистра из-за чего повышаем вероятность выпадения цифр с 10 : 62 к 10 : 36. Таким образом, реальная вероятность для каждой из цифр в пароле (учитывая и обязательные символы) будет на 85% превышать среднюю. А по дополнительному условию задачи (хотя в тестах это не отображено) значение такого превышения не должно быть больше 50%.
Вместо заключения. Код этой функции весьма любопытен, занимателен, местами остроумен, проходит имеющиеся тесты на codewars, но всё же представляет собой write-only code. При изучении JS или прохождении кат он вполне приемлем (даже более того). Но в реальных проектах лучше делать код более понятным, надёжным и поддерживаемым.
Автору спасибо! Но я полагаю, что воистину сеньорским было бы решение в стиле code golf. Предлагаю перерешать задачу. А то Эльбрус какой-то невысокий.
Почему мидловское решение более тупое, чем джуновское? )))
задача решается за 4 переменных но можно и с 2 справиться
Я бы хотел чтобы весь ваш канал был наполнен только такими видео! Я бы смотрел нонстоп тогда)
Кайф, было интересно посмотреть на сеньорский вариант
Очень рады, что вам понравилось 💜
Пожалуйста, никогда не делайте так, как тут показано )))
Никогда не повторяйте за этим горе сеньёром помидором…
регулярные выражения нечитаемые и занимают много памяти
спасибо за интересный формат!
Это ж что ж за джун то такой? По моему навыки джунов недооценены. У меня 0 опыта работы в айти (ну тоесть я даже не джун) и как бы я решил как показано в последнем варианте)
с 0 опыта решил как показан в последнем варианте, где нужно знать библиотеку крипто и её методы? 😄 для кого эта лапша?)
2:00 - 7:10 Это даже для джуна слишком позорный код, у меня студенты в Шымкенте в ЦАЭИ пишут лучше. =) А всё остальное очень хорошо.
Видимо, нашему преподавателю сложнее всего было придумать вариант джуна, и поэтому немного перестарался 😂
Привет, скажи чем он позорный
функции ради функций и понтов, чем более качественно пишешь говнокод тем более ты синьер.
сам не мог написать как Senior, поэтому видос пауза 🤣🤣🤣🤣🤣🤣🤣🤣
Нам пришлось прервать съёмки, поэтому захотелось добавить юмора и пошутить 😄
@@ElbrusBootcamp сочувствую 😂
все гениальное просто потому сеньор лучше всех а вот решение мидла хуже чем у джуниора!!!
прикольно, столько умников в комментах с имбическим стажем, что возникает вопросы, что вы забыли тут? ))) смотрите контент чисто для профиков. Душнилы