Телеграм-канал с новостями веб-разработки, полезными материалами, возможностью участвовать в карьерных консультациях, мок-интервью и активным чатом на 4 000 ребят с самым разным опытом, присоединяйтесь! ✈ t.me/purple_code_channel 📚 Десятки доступных курсов по разработке, тестированию и DevOps на нашей супер-платформе - purpleschool.ru/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend 📚 Node.js - с нуля - purpleschool.ru/course/nodejs/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend 📚 NestJS - с нуля - purpleschool.ru/course/nestjs/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend Бесплатные материалы 🗂 Карьерные пути для развития в разработке под вашу ситуацию - purpleschool.ru/skills/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend 🗂 Курс «Основы разработки» - purpleschool.ru/course/code-basics/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend 🗂 Курс «CSS Flexbox» - purpleschool.ru/course/flexbox/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend
Прекрасные примеры. Можно было бы добавить архитектурных шаблонов. В данных примерах мы видим огромный объём бизнес логики, который находится в функциях утилитах, однако программист явно хотел выразить некоторые типы данных. Было бы полезно создать объекты значений. Если в качестве аргументов использовать типы, мы смогли бы избежать повторной валидации и смогли бы сделать единственную точку с логикой валидации и тестами этой логики.
Хочу задать вопрос.Нужно ли явно указивать тип для КАЖДОЙ переменной?для параметров функции?для возвращаемого значения функции?и дженерики для для таких методов как map и reduce к примеру?
итого конкретно к бэку тут только про апи и лишние запросы, кейсы ок вроде бы, а вроде интернет полон этими типичными ошибками, я к чему клоню, кейсов например решения оптимизации где большие нагрузки и как их решать, попробуй найди вообще. Те же видео все про разные БД с названием Все что необходимо знать, на деле это просто круд, а чуть сложнее что-то это уже не к нам, извините. Хочется черпать бест практис не на поверхностные примеры.
@@ulietaight решение больших нагрузок это отдельный концептуальный вопрос, который решается ещё на этапе планирование архитектору. Это кэш, индексы, поддержка нескольких инстансов, использование куба, партиционирование таблиц и прочее. Было бы странно, не заложив это в архитектуру, писать это на ревью)
Ну по поводу выпиливания типов и замены на строку в первом случае - крайне сомнительно. По идее, типы должны не дать занести левые значения, и вообще - будет способствовать пониманию, что вообще надо возвращать. Да и типы здесь простые, не мозголомная матрешка из дженериков, лучше пусть будет, чем нет, зачем без причины расширять.
А теперь гадай какие строки принимает getUtmDetailed. Если нужно было принимать любые строки, то мОжно было в union тип добавить string и оставить всё остальное в качестве подсказки разрабу.
На самом деле тут еще нарушены паттерны самого NestJS... Авторизация вынесена в отдельный сервис и дергается из других сервисов, хотя нужно было ее засунуть в guard, который этим и должен заниматься...
@@alcokoalco9278 guard только проверяет авторизован пользователь или нет, он есть. А вот сервис, который логинит, регистрирует или восстанавливает пароль как раз отдельный
Ну во-первых хочется отметить, что by design функция getUtmDetailed выглядит очень странно. Я не могу с уверенностью скзаать, что тут что-то не так, потому что не вижу контекста, но по-моему то, что она может принять строку, не входящую в пул зарегестрированных + при это может не получить строку в принципе ( получить undefined на вход ) - довольно странно. То есть если приходит из какого-то инпута, типа ответа базы или http запроса и мы неможем явно контроллировать тип - окей, это объясняет, почему мы в принципе не ограничиваемся 1 enum`ом, просто не испытывая надобности в создании какой-либо функции. Но даже в таком случае я не понимаю, как и почему на вход может прийти undefined. То есть вышестоящие узлы должны должны каким-то образом это предотвращать. Ну опять же, я досконально не разбираюсь в общей логике проекта, мб это ошибочное предположение. Что касается финального состояния функции, после рефактора - ну на мой вкус конечно такое себе, что у нас функция может вернуть строку, а может null. Почему бы не вернуть пустую строку? Так или иначе всё приведёт к тому, что где-то сверху будет проверять результат, который функия вернёт, и проверять скорее всего примерно так: !getUtmDetalied(...), пустая строка в плане логики ничего не изменит, но у вас функция будет возвращать один и тот же тип, что логично и, о боже, извините что я этого говорю, лучше с точки зрения перфоменса на 0.00000001 наносекунду. По-моему в идеале эта функция должна принимать string и возвращать string, эта портянка типов выглядит крайне смущающе. Ну вот опять же, поднявшись на уровне выше, к функции getSource, мы опять видим string | undefined, не лучше ли просто где-то 1 раз сделать || '' и впоследствии принимать уже тип, просто как string, ладно, когда у нас этот тип растягивается на 2 уровня, а вот когда на 12...
Насколько я видел, то в динамически типизированных языках функции часто выдают либо нужный тип, либо None(null, nil и т.п.) И это очень удобно, потому что пустая строка иногда это тоже валидные данные
@@diam0nddangel336 ну смотря для чего. Если мы на выходе результат чекаем на true/false, то скажем так, в данном случае пустрая строка - невалидные данные. Возвращать null - окей для объекта. Потому что примерно для этого данный тип в рамках js`a и существует. А если вы хотите передать для любого другого типа какое-то falsy значение, то вы можете использовать пустую строку, 0, 0n и тд. Я не эксперт в других языках, но по-моему null в js довольно сильно по своей задумке отличается от null в каком-либо языке, где нет такого типа как undefined.
@Гооол-й4ч условно(условно!!!) если функция возвращает позицию курсора мыши по X. В таком случае null как раз единственное верное решение. 0 ведь валидное значение.
@@diam0nddangel336 в этом случае - да, семантически чтобы сигнлазировать ошибку нужно возвращать что-либо другое, 0 не подойдёт. Но по-моему это опять же проблема дизайна, такая функция не должна иметь возможности сломаться в принципе. Ну и опять же, подобные дилеммы в принципе возникают из-за того, что мы А) обрабатываем в функциях кейсы, которые до них в принципе доходить не должны Б) придумываем чтобы вернуть из функции, вместо того чтобы выбросить исключение. Потому что если у нас уже каким-то образом произошло так, что вледствие чего-либо у нас функция, отслеживающая позицию курсора, ломается и не может нормально выполнять свою работу, ну наверное нужно бросать экспешн и опускать занавес. Да и если дальше пойти, то фунция, возврщающая Date момента, когда юзер оплатил подписку может возвращать null, который просто-напросто говорит о том, что он её не оплачивал, но при этом в ней может быть какой-то кейс, из-за которого мы должны вернуть ( ссылаясь на предолженный флоу ) null в качестве знака провала. Ну тут мы как бы тоже не в состоянии точно понять, у нас пришло falsy значение, потому что так и должно было произойти или потому что что-то пошло не так. Тут единственный стабильный случай сигнлазиации, что что-то не так это throw.
@@Ромчик_Ёпта.service или controller это обозначение типа данного класса, который внутри. Это соглашение Nest. А через тире - название уже доменной области или функции из 2х слов
Там как бы вопрос на каком есть. Я временами ,гоняя тесты, использовал по 10_000_000+ значений и там всё равно иногда object в этом плане справлялся лучше. Хоть вроде как по всем канонам Map должен лучше справляться с операциями добавления/чтения. А если разница в перфоменсе и есть в пользу Map, то, как правило, крайне незначительная, поэтому я вообще не уверен, насколько рационально его использовать. Учитывая что и синтаксис менее привычный и между модулями в таком формате гонять дату - такое себе. Ну а ещё в реалях разработки всегда вставёт вопрос, а при билде твоего проекта, на выходе, твой Map или Set они вообще останутся таковыми, или в ходе использования каких-то полифилов превратятся в обычный Object.
Телеграм-канал с новостями веб-разработки, полезными материалами, возможностью участвовать в карьерных консультациях, мок-интервью и активным чатом на 4 000 ребят с самым разным опытом, присоединяйтесь!
✈ t.me/purple_code_channel
📚 Десятки доступных курсов по разработке, тестированию и DevOps на нашей супер-платформе - purpleschool.ru/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend
📚 Node.js - с нуля - purpleschool.ru/course/nodejs/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend
📚 NestJS - с нуля - purpleschool.ru/course/nestjs/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend
Бесплатные материалы
🗂 Карьерные пути для развития в разработке под вашу ситуацию - purpleschool.ru/skills/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend
🗂 Курс «Основы разработки» - purpleschool.ru/course/code-basics/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend
🗂 Курс «CSS Flexbox» - purpleschool.ru/course/flexbox/?D0%BA%D0%BE%D0%B4-%D1%80%D0%B5%D0%B2%D1%8C%D1%8E.+%D1%81%D0%BB%D0%B0%D0%B1%D1%8B%D0%B9+backend
Про CQRS в Nestjs было бы интересно посмотреть
@@ColorKat 👍
Очень сильно хочется увидеть обучение про CQRS, из ваших уст Антон
Прекрасные примеры. Можно было бы добавить архитектурных шаблонов. В данных примерах мы видим огромный объём бизнес логики, который находится в функциях утилитах, однако программист явно хотел выразить некоторые типы данных. Было бы полезно создать объекты значений. Если в качестве аргументов использовать типы, мы смогли бы избежать повторной валидации и смогли бы сделать единственную точку с логикой валидации и тестами этой логики.
Хочу задать вопрос.Нужно ли явно указивать тип для КАЖДОЙ переменной?для параметров функции?для возвращаемого значения функции?и дженерики для для таких методов как map и reduce к примеру?
Главное чтобы код работал)
Nope
главное чтобы деньги платили, а сколько, уже не важно, ага
@@tolyachernov7849 точно нет
Там где лишние запросы, просто вынесите в интецептор респонсов, зачем везде вставлять в контроллере этот мем)
@@ГосподинНикто-б7е 👍
итого конкретно к бэку тут только про апи и лишние запросы, кейсы ок вроде бы, а вроде интернет полон этими типичными ошибками, я к чему клоню, кейсов например решения оптимизации где большие нагрузки и как их решать, попробуй найди вообще. Те же видео все про разные БД с названием Все что необходимо знать, на деле это просто круд, а чуть сложнее что-то это уже не к нам, извините. Хочется черпать бест практис не на поверхностные примеры.
@@ulietaight решение больших нагрузок это отдельный концептуальный вопрос, который решается ещё на этапе планирование архитектору. Это кэш, индексы, поддержка нескольких инстансов, использование куба, партиционирование таблиц и прочее. Было бы странно, не заложив это в архитектуру, писать это на ревью)
Ну по поводу выпиливания типов и замены на строку в первом случае - крайне сомнительно. По идее, типы должны не дать занести левые значения, и вообще - будет способствовать пониманию, что вообще надо возвращать. Да и типы здесь простые, не мозголомная матрешка из дженериков, лучше пусть будет, чем нет, зачем без причины расширять.
@@CJIu3eHb если бы они далее использовались по коду, то да
Будут ли уроки по другим технологиям на бэке? Hono, elysia, encore
@@virtual5754 вполне
А какое приложение вы используете, когда рисуете/обводите какие-то элементы в видео ?
@@ArtemKharchuk screen brush
Спасибо больше
лучше еще импорты разделять на пользовательские и библиотечные. Точно не будет лишним
👍
А теперь гадай какие строки принимает getUtmDetailed. Если нужно было принимать любые строки, то мОжно было в union тип добавить string и оставить всё остальное в качестве подсказки разрабу.
На самом деле тут еще нарушены паттерны самого NestJS... Авторизация вынесена в отдельный сервис и дергается из других сервисов, хотя нужно было ее засунуть в guard, который этим и должен заниматься...
@@alcokoalco9278 guard только проверяет авторизован пользователь или нет, он есть. А вот сервис, который логинит, регистрирует или восстанавливает пароль как раз отдельный
@@PurpleSchool Может я чего-то не понял, но метод isUserHasAdminRoleOnSite зачем вызывается?
Не понял почему === undefined? Вообще то это первая проблема в ревью должна быть. Typeof === string
Ну во-первых хочется отметить, что by design функция getUtmDetailed выглядит очень странно. Я не могу с уверенностью скзаать, что тут что-то не так, потому что не вижу контекста, но по-моему то, что она может принять строку, не входящую в пул зарегестрированных + при это может не получить строку в принципе ( получить undefined на вход ) - довольно странно.
То есть если приходит из какого-то инпута, типа ответа базы или http запроса и мы неможем явно контроллировать тип - окей, это объясняет, почему мы в принципе не ограничиваемся 1 enum`ом, просто не испытывая надобности в создании какой-либо функции. Но даже в таком случае я не понимаю, как и почему на вход может прийти undefined. То есть вышестоящие узлы должны должны каким-то образом это предотвращать. Ну опять же, я досконально не разбираюсь в общей логике проекта, мб это ошибочное предположение.
Что касается финального состояния функции, после рефактора - ну на мой вкус конечно такое себе, что у нас функция может вернуть строку, а может null. Почему бы не вернуть пустую строку? Так или иначе всё приведёт к тому, что где-то сверху будет проверять результат, который функия вернёт, и проверять скорее всего примерно так: !getUtmDetalied(...), пустая строка в плане логики ничего не изменит, но у вас функция будет возвращать один и тот же тип, что логично и, о боже, извините что я этого говорю, лучше с точки зрения перфоменса на 0.00000001 наносекунду.
По-моему в идеале эта функция должна принимать string и возвращать string, эта портянка типов выглядит крайне смущающе.
Ну вот опять же, поднявшись на уровне выше, к функции getSource, мы опять видим string | undefined, не лучше ли просто где-то 1 раз сделать || '' и впоследствии принимать уже тип, просто как string, ладно, когда у нас этот тип растягивается на 2 уровня, а вот когда на 12...
Насколько я видел, то в динамически типизированных языках функции часто выдают либо нужный тип, либо None(null, nil и т.п.) И это очень удобно, потому что пустая строка иногда это тоже валидные данные
@@diam0nddangel336 ну смотря для чего. Если мы на выходе результат чекаем на true/false, то скажем так, в данном случае пустрая строка - невалидные данные.
Возвращать null - окей для объекта. Потому что примерно для этого данный тип в рамках js`a и существует. А если вы хотите передать для любого другого типа какое-то falsy значение, то вы можете использовать пустую строку, 0, 0n и тд.
Я не эксперт в других языках, но по-моему null в js довольно сильно по своей задумке отличается от null в каком-либо языке, где нет такого типа как undefined.
@Гооол-й4ч условно(условно!!!) если функция возвращает позицию курсора мыши по X. В таком случае null как раз единственное верное решение. 0 ведь валидное значение.
@@diam0nddangel336 в этом случае - да, семантически чтобы сигнлазировать ошибку нужно возвращать что-либо другое, 0 не подойдёт. Но по-моему это опять же проблема дизайна, такая функция не должна иметь возможности сломаться в принципе. Ну и опять же, подобные дилеммы в принципе возникают из-за того, что мы
А) обрабатываем в функциях кейсы, которые до них в принципе доходить не должны
Б) придумываем чтобы вернуть из функции, вместо того чтобы выбросить исключение.
Потому что если у нас уже каким-то образом произошло так, что вледствие чего-либо у нас функция, отслеживающая позицию курсора, ломается и не может нормально выполнять свою работу, ну наверное нужно бросать экспешн и опускать занавес.
Да и если дальше пойти, то фунция, возврщающая Date момента, когда юзер оплатил подписку может возвращать null, который просто-напросто говорит о том, что он её не оплачивал, но при этом в ней может быть какой-то кейс, из-за которого мы должны вернуть ( ссылаясь на предолженный флоу ) null в качестве знака провала. Ну тут мы как бы тоже не в состоянии точно понять, у нас пришло falsy значение, потому что так и должно было произойти или потому что что-то пошло не так.
Тут единственный стабильный случай сигнлазиации, что что-то не так это throw.
@Гооол-й4ч полностью согласен
Почему некоторые файлы называются через точку, например: "stats.services.tsx", а некоторые обычно, через тире? В чем разница?
@@Ромчик_Ёпта.service или controller это обозначение типа данного класса, который внутри. Это соглашение Nest. А через тире - название уже доменной области или функции из 2х слов
@PurpleSchool понял, спасибо!
Антон, напомни как называется тема в VS Code
@@icefrost5844 PurpleSchool Theme
Что с резкостью у видео? Её прям слишком много
return map ?? ‘other’
Куда кинуть можно на ревю код ?
@@boyywnkobe мы разбираем обычно код учеников или наших ребят из студии
В первом блоке можное было сделать еще проще return .get( ) || "Other";
почему map.get(key), а не object.key ?
@@mehanoid41 потому как это Map
@@PurpleSchool я вижу, что ты создал мапу) я не понимаю зачем это именно мап, а не просто объект?
я понимаю, что мап выгоднее на больших объёмах, но тут именно сёрчи, а их мало. инициализация объекта быстрее мапы. поэтому и спрашиваю, зачем мап?
Ддя новчиков.
1. На таком количестве возможных значений поля - нет абсолюно никакой разницы юзать Map или простой обьект
@@PimiTree для производительности да, а для чтения кода разница есть. Это оптимизация не ради скорости
Там как бы вопрос на каком есть. Я временами ,гоняя тесты, использовал по 10_000_000+ значений и там всё равно иногда object в этом плане справлялся лучше. Хоть вроде как по всем канонам Map должен лучше справляться с операциями добавления/чтения. А если разница в перфоменсе и есть в пользу Map, то, как правило, крайне незначительная, поэтому я вообще не уверен, насколько рационально его использовать. Учитывая что и синтаксис менее привычный и между модулями в таком формате гонять дату - такое себе. Ну а ещё в реалях разработки всегда вставёт вопрос, а при билде твоего проекта, на выходе, твой Map или Set они вообще останутся таковыми, или в ходе использования каких-то полифилов превратятся в обычный Object.
level api
👍