Код-ревью. Слабый backend на Node.js & Nest.js. 7 ошибок. Работа с Typescript

Поделиться
HTML-код
  • Опубликовано: 8 фев 2025

Комментарии • 53

  • @PurpleSchool
    @PurpleSchool  7 дней назад

    Телеграм-канал с новостями веб-разработки, полезными материалами, возможностью участвовать в карьерных консультациях, мок-интервью и активным чатом на 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

  • @ColorKat
    @ColorKat 7 дней назад +22

    Про CQRS в Nestjs было бы интересно посмотреть

    • @PurpleSchool
      @PurpleSchool  7 дней назад

      @@ColorKat 👍

    • @auranode4542
      @auranode4542 7 дней назад +1

      Очень сильно хочется увидеть обучение про CQRS, из ваших уст Антон

  • @DzhigurdaAnton
    @DzhigurdaAnton 6 дней назад

    Прекрасные примеры. Можно было бы добавить архитектурных шаблонов. В данных примерах мы видим огромный объём бизнес логики, который находится в функциях утилитах, однако программист явно хотел выразить некоторые типы данных. Было бы полезно создать объекты значений. Если в качестве аргументов использовать типы, мы смогли бы избежать повторной валидации и смогли бы сделать единственную точку с логикой валидации и тестами этой логики.

  • @ЯкимівДенис-р7л
    @ЯкимівДенис-р7л 12 часов назад

    Хочу задать вопрос.Нужно ли явно указивать тип для КАЖДОЙ переменной?для параметров функции?для возвращаемого значения функции?и дженерики для для таких методов как map и reduce к примеру?

  • @tolyachernov7849
    @tolyachernov7849 7 дней назад +2

    Главное чтобы код работал)

    • @vyciox
      @vyciox 7 дней назад

      Nope

    • @ulietaight
      @ulietaight 7 дней назад

      главное чтобы деньги платили, а сколько, уже не важно, ага

    • @PurpleSchool
      @PurpleSchool  7 дней назад +2

      @@tolyachernov7849 точно нет

  • @ГосподинНикто-б7е
    @ГосподинНикто-б7е 7 дней назад +6

    Там где лишние запросы, просто вынесите в интецептор респонсов, зачем везде вставлять в контроллере этот мем)

    • @PurpleSchool
      @PurpleSchool  6 дней назад

      @@ГосподинНикто-б7е 👍

  • @ulietaight
    @ulietaight 7 дней назад +4

    итого конкретно к бэку тут только про апи и лишние запросы, кейсы ок вроде бы, а вроде интернет полон этими типичными ошибками, я к чему клоню, кейсов например решения оптимизации где большие нагрузки и как их решать, попробуй найди вообще. Те же видео все про разные БД с названием Все что необходимо знать, на деле это просто круд, а чуть сложнее что-то это уже не к нам, извините. Хочется черпать бест практис не на поверхностные примеры.

    • @PurpleSchool
      @PurpleSchool  7 дней назад +1

      @@ulietaight решение больших нагрузок это отдельный концептуальный вопрос, который решается ещё на этапе планирование архитектору. Это кэш, индексы, поддержка нескольких инстансов, использование куба, партиционирование таблиц и прочее. Было бы странно, не заложив это в архитектуру, писать это на ревью)

  • @CJIu3eHb
    @CJIu3eHb 6 дней назад +2

    Ну по поводу выпиливания типов и замены на строку в первом случае - крайне сомнительно. По идее, типы должны не дать занести левые значения, и вообще - будет способствовать пониманию, что вообще надо возвращать. Да и типы здесь простые, не мозголомная матрешка из дженериков, лучше пусть будет, чем нет, зачем без причины расширять.

    • @PurpleSchool
      @PurpleSchool  6 дней назад

      @@CJIu3eHb если бы они далее использовались по коду, то да

  • @virtual5754
    @virtual5754 7 дней назад +1

    Будут ли уроки по другим технологиям на бэке? Hono, elysia, encore

  • @ArtemKharchuk
    @ArtemKharchuk 7 дней назад +1

    А какое приложение вы используете, когда рисуете/обводите какие-то элементы в видео ?

  • @koffer5759
    @koffer5759 4 дня назад

    лучше еще импорты разделять на пользовательские и библиотечные. Точно не будет лишним

  • @xeleos
    @xeleos 6 дней назад

    А теперь гадай какие строки принимает getUtmDetailed. Если нужно было принимать любые строки, то мОжно было в union тип добавить string и оставить всё остальное в качестве подсказки разрабу.

  • @alcokoalco9278
    @alcokoalco9278 2 дня назад

    На самом деле тут еще нарушены паттерны самого NestJS... Авторизация вынесена в отдельный сервис и дергается из других сервисов, хотя нужно было ее засунуть в guard, который этим и должен заниматься...

    • @PurpleSchool
      @PurpleSchool  2 дня назад

      @@alcokoalco9278 guard только проверяет авторизован пользователь или нет, он есть. А вот сервис, который логинит, регистрирует или восстанавливает пароль как раз отдельный

    • @alcokoalco9278
      @alcokoalco9278 2 дня назад

      @@PurpleSchool Может я чего-то не понял, но метод isUserHasAdminRoleOnSite зачем вызывается?

  • @MrKatunins
    @MrKatunins 6 дней назад

    Не понял почему === undefined? Вообще то это первая проблема в ревью должна быть. Typeof === string

  • @Гооол-й4ч
    @Гооол-й4ч 6 дней назад

    Ну во-первых хочется отметить, что by design функция getUtmDetailed выглядит очень странно. Я не могу с уверенностью скзаать, что тут что-то не так, потому что не вижу контекста, но по-моему то, что она может принять строку, не входящую в пул зарегестрированных + при это может не получить строку в принципе ( получить undefined на вход ) - довольно странно.
    То есть если приходит из какого-то инпута, типа ответа базы или http запроса и мы неможем явно контроллировать тип - окей, это объясняет, почему мы в принципе не ограничиваемся 1 enum`ом, просто не испытывая надобности в создании какой-либо функции. Но даже в таком случае я не понимаю, как и почему на вход может прийти undefined. То есть вышестоящие узлы должны должны каким-то образом это предотвращать. Ну опять же, я досконально не разбираюсь в общей логике проекта, мб это ошибочное предположение.
    Что касается финального состояния функции, после рефактора - ну на мой вкус конечно такое себе, что у нас функция может вернуть строку, а может null. Почему бы не вернуть пустую строку? Так или иначе всё приведёт к тому, что где-то сверху будет проверять результат, который функия вернёт, и проверять скорее всего примерно так: !getUtmDetalied(...), пустая строка в плане логики ничего не изменит, но у вас функция будет возвращать один и тот же тип, что логично и, о боже, извините что я этого говорю, лучше с точки зрения перфоменса на 0.00000001 наносекунду.
    По-моему в идеале эта функция должна принимать string и возвращать string, эта портянка типов выглядит крайне смущающе.
    Ну вот опять же, поднявшись на уровне выше, к функции getSource, мы опять видим string | undefined, не лучше ли просто где-то 1 раз сделать || '' и впоследствии принимать уже тип, просто как string, ладно, когда у нас этот тип растягивается на 2 уровня, а вот когда на 12...

    • @diam0nddangel336
      @diam0nddangel336 3 дня назад

      Насколько я видел, то в динамически типизированных языках функции часто выдают либо нужный тип, либо None(null, nil и т.п.) И это очень удобно, потому что пустая строка иногда это тоже валидные данные

    • @Гооол-й4ч
      @Гооол-й4ч 3 дня назад

      @@diam0nddangel336 ну смотря для чего. Если мы на выходе результат чекаем на true/false, то скажем так, в данном случае пустрая строка - невалидные данные.
      Возвращать null - окей для объекта. Потому что примерно для этого данный тип в рамках js`a и существует. А если вы хотите передать для любого другого типа какое-то falsy значение, то вы можете использовать пустую строку, 0, 0n и тд.
      Я не эксперт в других языках, но по-моему null в js довольно сильно по своей задумке отличается от null в каком-либо языке, где нет такого типа как undefined.

    • @diam0nddangel336
      @diam0nddangel336 3 дня назад

      @Гооол-й4ч условно(условно!!!) если функция возвращает позицию курсора мыши по X. В таком случае null как раз единственное верное решение. 0 ведь валидное значение.

    • @Гооол-й4ч
      @Гооол-й4ч 3 дня назад

      @@diam0nddangel336 в этом случае - да, семантически чтобы сигнлазировать ошибку нужно возвращать что-либо другое, 0 не подойдёт. Но по-моему это опять же проблема дизайна, такая функция не должна иметь возможности сломаться в принципе. Ну и опять же, подобные дилеммы в принципе возникают из-за того, что мы
      А) обрабатываем в функциях кейсы, которые до них в принципе доходить не должны
      Б) придумываем чтобы вернуть из функции, вместо того чтобы выбросить исключение.
      Потому что если у нас уже каким-то образом произошло так, что вледствие чего-либо у нас функция, отслеживающая позицию курсора, ломается и не может нормально выполнять свою работу, ну наверное нужно бросать экспешн и опускать занавес.
      Да и если дальше пойти, то фунция, возврщающая Date момента, когда юзер оплатил подписку может возвращать null, который просто-напросто говорит о том, что он её не оплачивал, но при этом в ней может быть какой-то кейс, из-за которого мы должны вернуть ( ссылаясь на предолженный флоу ) null в качестве знака провала. Ну тут мы как бы тоже не в состоянии точно понять, у нас пришло falsy значение, потому что так и должно было произойти или потому что что-то пошло не так.
      Тут единственный стабильный случай сигнлазиации, что что-то не так это throw.

    • @diam0nddangel336
      @diam0nddangel336 3 дня назад

      @Гооол-й4ч полностью согласен

  • @Ромчик_Ёпта
    @Ромчик_Ёпта 7 дней назад

    Почему некоторые файлы называются через точку, например: "stats.services.tsx", а некоторые обычно, через тире? В чем разница?

    • @PurpleSchool
      @PurpleSchool  7 дней назад

      @@Ромчик_Ёпта.service или controller это обозначение типа данного класса, который внутри. Это соглашение Nest. А через тире - название уже доменной области или функции из 2х слов

    • @Ромчик_Ёпта
      @Ромчик_Ёпта 6 дней назад

      @PurpleSchool понял, спасибо!

  • @icefrost5844
    @icefrost5844 7 дней назад

    Антон, напомни как называется тема в VS Code

    • @PurpleSchool
      @PurpleSchool  7 дней назад

      @@icefrost5844 PurpleSchool Theme

  • @youtube-user-viwer
    @youtube-user-viwer 6 дней назад

    Что с резкостью у видео? Её прям слишком много

  • @NonameDiablo
    @NonameDiablo 6 дней назад

    return map ?? ‘other’

  • @boyywnkobe
    @boyywnkobe 7 дней назад

    Куда кинуть можно на ревю код ?

    • @PurpleSchool
      @PurpleSchool  7 дней назад

      @@boyywnkobe мы разбираем обычно код учеников или наших ребят из студии

  • @Epic0n
    @Epic0n 6 дней назад

    В первом блоке можное было сделать еще проще return .get( ) || "Other";

  • @mehanoid41
    @mehanoid41 5 дней назад

    почему map.get(key), а не object.key ?

    • @PurpleSchool
      @PurpleSchool  5 дней назад

      @@mehanoid41 потому как это Map

    • @mehanoid41
      @mehanoid41 3 дня назад

      @@PurpleSchool я вижу, что ты создал мапу) я не понимаю зачем это именно мап, а не просто объект?

    • @mehanoid41
      @mehanoid41 3 дня назад

      я понимаю, что мап выгоднее на больших объёмах, но тут именно сёрчи, а их мало. инициализация объекта быстрее мапы. поэтому и спрашиваю, зачем мап?

  • @PimiTree
    @PimiTree 7 дней назад +1

    Ддя новчиков.
    1. На таком количестве возможных значений поля - нет абсолюно никакой разницы юзать Map или простой обьект

    • @PurpleSchool
      @PurpleSchool  7 дней назад +1

      @@PimiTree для производительности да, а для чтения кода разница есть. Это оптимизация не ради скорости

    • @Гооол-й4ч
      @Гооол-й4ч 6 дней назад

      Там как бы вопрос на каком есть. Я временами ,гоняя тесты, использовал по 10_000_000+ значений и там всё равно иногда object в этом плане справлялся лучше. Хоть вроде как по всем канонам Map должен лучше справляться с операциями добавления/чтения. А если разница в перфоменсе и есть в пользу Map, то, как правило, крайне незначительная, поэтому я вообще не уверен, насколько рационально его использовать. Учитывая что и синтаксис менее привычный и между модулями в таком формате гонять дату - такое себе. Ну а ещё в реалях разработки всегда вставёт вопрос, а при билде твоего проекта, на выходе, твой Map или Set они вообще останутся таковыми, или в ходе использования каких-то полифилов превратятся в обычный Object.

  • @denysbilas3670
    @denysbilas3670 7 дней назад

    level api