Сергей Петрелевич
Сергей Петрелевич
  • Видео 35
  • Просмотров 135 109
Знакомство с Micronaut
Пример CRUD приложения на Micronaut.
Исходный код:
github.com/petrelevich/jvm-digging/tree/master/micronaut-demo
Чат в телеге для вопросов и обсуждений:
t.me/jvm_home
Просмотров: 558

Видео

Java virtual Thread
Просмотров 418Месяц назад
Посмотрим, что такое virtual Thread (виртуальные потоки) в Java и для чего они нужны. Исходный код: github.com/petrelevich/jvm-digging/tree/master/virtual-thread Чат в телеге для вопросов и обсуждений: t.me/jvm_home
Знакомство с Armeria
Просмотров 3512 месяца назад
На примере приложения с TINKOFF INVEST API познакомимся с фреймворком Armeria. Исходный код: github.com/petrelevich/trading-public Чат в телеге для вопросов и обсуждений: t.me/jvm_home
TCP Log-appender на java (NIO)
Просмотров 2755 месяцев назад
В предыдущем видео (ruclips.net/video/Krsx3IhO8nM/видео.html) был разработан TCP Log-сервер. Сейчас для него сделаем appender для отправки логов. Исходный код: github.com/petrelevich/tcp-server-client Чат в телеге для вопросов и обсуждений: t.me/jvm_home
TCP Log-сервер на java (NIO)
Просмотров 2655 месяцев назад
В предыдущем видео (ruclips.net/video/QZlklg5GzX0/видео.htmlsi=sIX4DnOFL4qoO0_1) был оптимизирован TCP сервер. Сейчас на его основе сделаем сервер для приема логов. Для парсинга потока байт применим конечный автомат. Исходный код: github.com/petrelevich/tcp-server-client Чат в телеге для вопросов и обсуждений: t.me/jvm_home Рассказ про конечные автоматы: ruclips.net/video/TwyrwgFVyy0/видео.html...
Оптимизация неблокирующего TCP сервера на java (NIO)
Просмотров 3895 месяцев назад
В предыдущем видео (ruclips.net/video/KhSMQJ3TaGw/видео.htmlsi=c4k2NJzw0KoGXDaU) был разработан TCP сервер. Сейчас проведем нагрузочное тестирование и оптимизируем потребление памяти. Исходный код: github.com/petrelevich/tcp-server-client Чат в телеге для вопросов и обсуждений: t.me/jvm_home
Неблокирующий TCP сервер на java (NIO)
Просмотров 9156 месяцев назад
В предыдущем видео (ruclips.net/video/udFia_0ZB0Q/видео.htmlsi=SOS6R56Bww1gY_Ae) мы посмотрели как можно реализовать блокирующий сервер. Сейчас давайте взглянем на неблокирующий вариант TCP сервера на java. Исходный код: github.com/petrelevich/tcp-server-client Чат в телеге для вопросов и обсуждений: t.me/jvm_home
Блокирующий TCP сервер на java
Просмотров 6106 месяцев назад
На простом примере посмотрим как можно реализовать блокирующий TCP сервер на java. Исходный код: github.com/petrelevich/tcp-server-client Чат в телеге для вопросов и обсуждений: t.me/jvm_home
Рассказ про exactly once в kafka
Просмотров 1,1 тыс.8 месяцев назад
Транзакции в Kafta предназначены для работы с двумя очередями. А что делать, если надо брать сообщение из очереди и обрабатывать, причем строго один раз. Об этом и поговорим. Исходный код примеров: github.com/petrelevich/jvm-digging/tree/master/kafka Чат в телеге для вопросов и обсуждений: t.me/jvm_home
Конечные автоматы в Java
Просмотров 1,1 тыс.11 месяцев назад
Посмотрим, что такое конечные автоматы и как их можно применить в Java Это техническая часть вебинара: ruclips.net/user/live3r8sjj434FU?feature=share Обучаем программированию на Java: otus.ru/lessons/java-professional/ Примеры: github.com/petrelevich/jvm-digging/tree/master/statemachine Пример применения идеи автомата для парсинга потока байт: ruclips.net/video/Krsx3IhO8nM/видео.htmlsi=c6Wz0-hb...
Составной первичный ключ, Spring Data Jdbc
Просмотров 60311 месяцев назад
Посмотрим, как в Spring Data Jdbc можно работать с таблицами, у которых составной первичный ключ. Исходный код: github.com/petrelevich/jvm-digging/tree/master/springDataJdbc Чат в телеге для вопросов и обсуждений: t.me/jvm_home
reactor kafka
Просмотров 89511 месяцев назад
Рассмотрим, что такое Reactor Kafka и узнаем как им пользоваться. Это техническая часть вебинара: ruclips.net/user/liveRjhOkvEqFJA?feature=share Обучаем программированию на Java: otus.ru/lessons/java-professional/ Примеры: github.com/petrelevich/jvm-digging/tree/master/kafka Чат в телеге для вопросов и обсуждений: t.me/jvm_home
kafka в приложениях на SpringBoot
Просмотров 3,1 тыс.Год назад
Рассмотрим, как использовать стартер springBoot для работы с Kafka. Это техническая часть вебинара: ruclips.net/user/live9FikRH8rXas?feature=share ruclips.net/user/liveY-ClxJozvCo?feature=share Обучаем применению Kafka: otus.ru/lessons/kafka/ Примеры: github.com/petrelevich/jvm-digging/tree/master/kafka-spring Чат в телеге для вопросов и обсуждений: t.me/jvm_home
Примеры применения caffeine и ehcache в java
Просмотров 947Год назад
В этом видео рассмотрим примеры применения популярных кешей caffeine и ehcache в java Примеры: github.com/petrelevich/jvm-digging/tree/master/cacheDemo Чат в телеге для вопросов и обсуждений: t.me/jvm_home
r2dbc. Реактивное подключение к Postgresql в приложениях на Java
Просмотров 1,2 тыс.Год назад
Рассмотрим, как применить r2dbc для реактивного подключения к Postgresql Это техническая часть вебинара: ruclips.net/user/liveWPodh3b0clY?feature=share Обучаем программированию на java: otus.ru/lessons/java-professional/ Примеры: github.com/petrelevich/jvm-digging/tree/master/r2dbc Чат в телеге для вопросов и обсуждений: t.me/jvm_home
Кто такие дженерики?
Просмотров 1 тыс.Год назад
Кто такие дженерики?
Объектно-ориентированное и функциональное программирование
Просмотров 708Год назад
Объектно-ориентированное и функциональное программирование
gradle plugin на Kotlin для проектов на Java
Просмотров 9582 года назад
gradle plugin на Kotlin для проектов на Java
Serializer и Deserializer в Kafka
Просмотров 1,1 тыс.2 года назад
Serializer и Deserializer в Kafka
Kafka consumer. Метод poll
Просмотров 4,1 тыс.2 года назад
Kafka consumer. Метод poll
Применение kafka для связи микросервисов на Java Spring Boot
Просмотров 32 тыс.2 года назад
Применение kafka для связи микросервисов на Java Spring Boot
Основы Java collections
Просмотров 1,8 тыс.2 года назад
Основы Java collections
Пример реактивного приложения на Spring WebFlux
Просмотров 7 тыс.2 года назад
Пример реактивного приложения на Spring WebFlux
Reactor Netty
Просмотров 2,6 тыс.2 года назад
Reactor Netty
Пример бота Telegram на java
Просмотров 3,8 тыс.2 года назад
Пример бота Telegram на java
Введение в Gradle
Просмотров 13 тыс.2 года назад
Введение в Gradle
Deploy микросервисов на Java Spring Boot в Kubernetes
Просмотров 9 тыс.2 года назад
Deploy микросервисов на Java Spring Boot в Kubernetes
Разработка двух микросервисов на Java Spring Boot
Просмотров 22 тыс.2 года назад
Разработка двух микросервисов на Java Spring Boot
gRPC для микросервисов или не REST-ом единым
Просмотров 4,3 тыс.3 года назад
gRPC для микросервисов или не REST-ом единым
Пример применения технологии gRPC
Просмотров 8 тыс.3 года назад
Пример применения технологии gRPC

Комментарии

  • @alex45788
    @alex45788 10 дней назад

    Сергей, у Вас нет в планах сделать видео с разбором популярных и нетривиальных операторов Project Reator ? Как бы это было бы круто 🥺

    • @petrelevich
      @petrelevich 10 дней назад

      Сейчас готовлю доклад про замену webflux на virtual thread. В нем как раз будут такие операторы. Т.е. про случаи, когда заменить будет трудно.

  • @alex45788
    @alex45788 11 дней назад

    Вопрос по коду. Создание KafkaReceiver (класс ReactiveReceiver) KafkaReceiver.create(options) .receiveAutoAck() .concatMap(consumerRecordFlux -> { log.info("consumerRecordFlux done, commit"); return consumerRecordFlux; }) .retryWhen(Retry.backoff(3, Duration.of(10L, ChronoUnit.SECONDS))); 1. Почему выбран метод concatMap? Какая его логика? Мы могли бы использовать например doOnNext для логирования очередного элемента потока. 2. Почему используется backoff в retryWhen, а не fixedDelay например?

    • @petrelevich
      @petrelevich 11 дней назад

      1. concatMap преобразует Flux<Flux<ConsumerRecord<K, V>>> receiveAutoAck() в Flux<ConsumerRecord<K, V>>, doOnNext не подойдет 2. backoff реализует exponential backoff strategy, т.е. каждая следующая попытка будет выполняться с большим интервалом, а fixedDelay задает интервал фиксированный.

  • @gderuki
    @gderuki 24 дня назад

    +

  • @levaryazan
    @levaryazan 27 дней назад

    Отличное объяснение!! Спасибо.

  • @sergglav
    @sergglav 29 дней назад

    Спасибо! Стало быть, у Micronaut Reactor под капотом? Или его надо специально подключать?

    • @petrelevich
      @petrelevich 29 дней назад

      reactor приезжает транзитивно с другими зависимостями.

  • @immortal-spirit-13
    @immortal-spirit-13 29 дней назад

    Очень похоже на Spring Boot c WebFlux )) но я не увидел ни одной причины зачем использовать Micronaut вместо SpringBoot

    • @petrelevich
      @petrelevich 29 дней назад

      Ключевое преимущество - AOT-компиляция. Про это предполагаются следующие серии...

  • @mitruslatovous6
    @mitruslatovous6 Месяц назад

    Спасибо за просветительскую работу!

  • @exes5282
    @exes5282 Месяц назад

    Спасибо!!!!!!

  • @ivanstrelka3448
    @ivanstrelka3448 Месяц назад

    Спасибо!

  • @wildjoe6259
    @wildjoe6259 Месяц назад

    Спасибо!

  • @mitruslatovous6
    @mitruslatovous6 Месяц назад

    Спасибо! Понятное объяснение. Было очень интересно)

  • @sergglav
    @sergglav Месяц назад

    Сергей, огромное спасибо за видео! Как всегда всё познавательно и внятно, как на курсах)

  • @MrRomanvideo
    @MrRomanvideo Месяц назад

    Спасибо, интересно и полезно. Пример со Спринг Бута тоже было бы классно вместе посмотреть)

  • @user-gi2hx8zf1i
    @user-gi2hx8zf1i Месяц назад

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

  • @alex45788
    @alex45788 Месяц назад

    Жду шестую серию сериала)

  • @user-mb1dj3pk2d
    @user-mb1dj3pk2d Месяц назад

    Я думаю, что стоило хоть разок запустить приложение и показать как оно работает)))

    • @petrelevich
      @petrelevich Месяц назад

      да, это было бы полезно

  • @972gmailcom1
    @972gmailcom1 Месяц назад

    Интересно, но к сожалению "плохой звук": через наушники слышно нормально, а вот на средних динамиках не слышно.

  • @konstantinchvilyov9602
    @konstantinchvilyov9602 Месяц назад

    Спасибо. Без базы данных нельзя обойтись?.. Это же потеря скорости.

    • @petrelevich
      @petrelevich Месяц назад

      Можно обойтись, если не требуется гарантия exectly-once. Такая гарантия действительно редко нужна.

    • @konstantinchvilyov9602
      @konstantinchvilyov9602 Месяц назад

      @@petrelevich Странно, такая гарантия всегда была нужна на моих работах.

    • @petrelevich
      @petrelevich Месяц назад

      @@konstantinchvilyov9602 Например, exectly-once точно не надо в логгировании, телеметрии, социальных сетях и т.е., когда что-то иногда можно потерять. И exectly-once почти всегда обязателен в платежах.

  • @user-br4gt7xu2j
    @user-br4gt7xu2j 2 месяца назад

    Классный проект (особенно порадовал production-ready подход к разработке). Очень интересно будет следить за его развитием в полноценную систему. Такие видеосериалы с постепенным построением готовой неучебной платформы, на мой взгляд, как раз лучшие для обучения начинающего: позволяют понять для чего каждый элемент и чем отличаются подходы P.S. кстати, не понял, почему в качестве мапперов для таких объемных дто не использовался mapstruct, он легковесный и одной строкой заменяет все эти полотна кода?

    • @petrelevich
      @petrelevich 2 месяца назад

      >кстати, не понял, почему в качестве мапперов для таких объемных дто не использовался mapstruct, он легковесный и одной строкой заменяет все эти полотна кода? да, можно его использовать. И это еще один вопрос - а нужно ли тут вообще dto.

    • @user-br4gt7xu2j
      @user-br4gt7xu2j 2 месяца назад

      @@petrelevich ну сами по себе иммутабельные ДТО часто бывают полезны (помогают при формализации необходимого контракта для клиента, и полезны для его документирования, помогают при валидации данных, если модель анемична, могут часто помочь при дальнейших доработках, уменьшая связанность между моделью и интерфейсом клиента и т.п.), и при этом они "есть не просят" особо, как говорится, поэтому лично я полагаю, что лучше с ними, чем без них

  • @sequ3nce515
    @sequ3nce515 2 месяца назад

    Хорошее видео, спасибо :) Нет ли в планах создания полноценного курса по какой-либо из тем? Или если есть может кто-то сказать название и где можно приобрести?

    • @petrelevich
      @petrelevich 2 месяца назад

      Пока таких планов нет, но все возможно в будущем :)

  • @972gmailcom1
    @972gmailcom1 3 месяца назад

    Спасибо. Посмотрел позже. Было интересно и полезно.

  • @v.volkau
    @v.volkau 3 месяца назад

    Отличное видео, пересмотрел второй раз спустя время и всё понял. Замечательный пример про бармена. Пожалуйста, продолжайте использовать такие бытовые примеры для объяснения - очень хорошо запоминается.

  • @v.volkau
    @v.volkau 3 месяца назад

    Спасибо, отличное видео!

  • @immortal-spirit-13
    @immortal-spirit-13 3 месяца назад

    Петрелевич очень умный парень, хорошо доносит

  • @markostr
    @markostr 3 месяца назад

    Очень хорошо объяснили ! Спасибо !

  • @root924
    @root924 3 месяца назад

    Если guava есть в classpath, то по какой причине libApiUse ее не видит?

    • @petrelevich
      @petrelevich 3 месяца назад

      не видит, если используется scope - implementation

  • @user-hm8wx2us8l
    @user-hm8wx2us8l 4 месяца назад

    Из разряда "как нарисовать сову": 1. рисуем три кружка; 2. дорисовываем до совы. Отус такой ценник за свои курсы лупит, а лайф-кодинг поленился сделать даже на вводном уроке. Смотрите - это парсер, ну парсер и парсер, ничего особенного 😅 Спринг так же объясняете?) Это бин, ну бин и бин, ничего особенного, поехали дальше))

    • @petrelevich
      @petrelevich 4 месяца назад

      Что именно не понятно и требует детального пояснения?

  • @takezo_kyiv
    @takezo_kyiv 4 месяца назад

    Спасибо большое за видео! Очень познавательно

  • @user-xj4hi5ld4g
    @user-xj4hi5ld4g 5 месяцев назад

    откуда при раскладе 3 сек на источник и 2 сек на обработчик может возникнуть очередь? источник генерит медленнее чем обработчик обрабатывает. 1,2,3 источник 4,5 обработчик 4,5,6 источник 7,8 обработчик 7,8,9 источник

    • @petrelevich
      @petrelevich 5 месяцев назад

      какую очередь имеете в виду?

    • @user-xj4hi5ld4g
      @user-xj4hi5ld4g 5 месяцев назад

      @@petrelevich вот тут: 1 час 20 минут

    • @petrelevich
      @petrelevich 5 месяцев назад

      @@user-xj4hi5ld4g Пересмотрел, начиная с этого момента ruclips.net/video/UDGZV0tzPQ8/видео.htmlsi=WwyOF8Sv5okuUib_&t=4743 Ничего не услышал про "очередь".

    • @user-xj4hi5ld4g
      @user-xj4hi5ld4g 5 месяцев назад

      ​@@petrelevich там в комментах задан вопрос и вот текстовая расшифровка: 1:20:57 у вас есть некий некая задержка а на 1:21:15 звучит "и в итоге тут должно больше наплодиться.... чем больше работаем тем больше накапливается разница" это где будет накопление? и откуда возьмется накопление учитывая что генерация медленнее чем обработка?

    • @petrelevich
      @petrelevich 5 месяцев назад

      @@user-xj4hi5ld4g Теперь понятно, в чем вопрос. В классе DataProducerStringReactor данные генерируются без ограничения скорости, но потом добавляется задержка delayElements(Duration.ofSeconds(3)). Чтобы согласовать быстрый источник и медленный обработчик включается механизм backpressure. Это приводит к тому, что данные создаются в генераторе и буферизируются (накапливаются) пока потребитель не сможет их обработать. После обработки создается новая порция данных и они буферизируются, пока не обработаются. Понятно пояснил? Надо, наверное, видос на эту тему записать?

  • @sromankov6102
    @sromankov6102 5 месяцев назад

    спасибо очень информативно, только вот вопрос, как скажем из CI задать выбор энва? Определить две configMap и как-то выбирать между ними или же как-то по другому ?

    • @petrelevich
      @petrelevich 5 месяцев назад

      Второй configMap делать не надо. Лучше применить шаблонизатор типа Helm

  • @wildjoe6259
    @wildjoe6259 5 месяцев назад

    Спасибо!

  • @anjelomanoranjan3908
    @anjelomanoranjan3908 5 месяцев назад

    Сергей, спасибо за то, что предоставили исходный код) Это очень важно для новичков)

  • @anjelomanoranjan3908
    @anjelomanoranjan3908 5 месяцев назад

    Спасибо огромное) шикарное видео! Честно говоря, не помню чтобы встречал разорванное текстовое сообщение. Насколько знаю, текстовые сообщения передаются по протоколу TCP, а этот протокол должен ГАРАНТИРОВАТЬ целостность отправленных пакетов.

    • @petrelevich
      @petrelevich 5 месяцев назад

      Пакеты придут полностью, но длинные сообщения могут прийти по частям или наоборот вместе. Посмотрите предыдущее видео про нагрузочное тестирование. Там всплывали подобные моменты. И еще момент - в этом видео речь идет уже о "бизнес - логике", тут получение по частям максимально вероятно из-за буферизации на стороне "tcp-сервера".

    • @anjelomanoranjan3908
      @anjelomanoranjan3908 5 месяцев назад

      @@petrelevich благодарю за развёрнутый ответ

  • @wildjoe6259
    @wildjoe6259 5 месяцев назад

    Спасибо! Довольно познавательный цикл получился. Не так давно, нечто подобное у себя на проекте реализовывали с командой. За идею с применением концепции конечных автоматов в кейсе с парсингом, прям большой респект!

  • @MaximBodrov
    @MaximBodrov 5 месяцев назад

    Вопрос к Сергею, не первый раз уже слышу его мысль о важности groupID для консьюмера, т.е. если скопировать код из другого проекта и не изменить имя группы, то он (консьюмер) будет "красть" не свои сообщения. И вот тут у меня непонятки: ведь мы при настройке консюмера указываем еще и имя топика, на который он подписан. Я так понимал, для того чтобы он забирал по ошибке сообщения из другого проекта, нужно чтобы и имя группы, и имя топика совпало, а это еще более малый шанс

    • @petrelevich
      @petrelevich 5 месяцев назад

      Да, имя топика должно быть то же. И конечно, тот же инстанс kafka. Вероятность "кражи" зависит от характера приложения. Представьте, что это очередь заказов в магазине и куча систем работают с этой очередью: кто-то аналитику делает, кто-то отправку организует, кто-то уведомления рассылает. Для kafaka типовая ситуация, когда с одним топиком работает много систем.

  • @ekaterinagalkina7303
    @ekaterinagalkina7303 5 месяцев назад

    Смущает фраза из доки "that max.poll.records does not impact the underlying fetching behavior". Т.е. звучит так, что сетевые запросы - это одно, а poll() - другое, и на сетевые запросы к кафке настройка не влияет. Т.е. запрошенный объем данных где-то еще кэшируется, а that max.poll.records - всего лишь размер массива. max.poll.records The maximum number of records returned in a single call to poll(). Note, that max.poll.records does not impact the underlying fetching behavior. The consumer will cache the records from each fetch request and returns them incrementally from each poll. А для fetch другие настройки есть - максимальный размер в байтах и т.д. Но тогда непонятно, как по poll кафка определяет, что консьюмер упал. Правда, есть еще другая настройка heartbeat.interval.ms для пинга от консьюмера.

    • @petrelevich
      @petrelevich 5 месяцев назад

      Параметры запроса к брокеру определяются конфигом: package org.apache.kafka.clients.consumer.internals; public class FetchConfig<K, V> { final int fetchSize; final int maxPollRecords; где this.fetchSize = config.getInt(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG); this.maxPollRecords = config.getInt(ConsumerConfig.MAX_POLL_RECORDS_CONFIG); сам запрос формируется тут: package org.apache.kafka.clients.consumer.internals; public abstract class AbstractFetch<K, V> один из его параметров .setMaxBytes(fetchConfig.maxBytes) а fetchSize используется в вычитывании из внутреннего буфера. Вот с этим буфером еще надо поразбираться.

  • @evgenykuznetsov7490
    @evgenykuznetsov7490 5 месяцев назад

    топ как всегда, крутая тема👍

  • @qreol136
    @qreol136 6 месяцев назад

    Житель из деревни

  • @LighterDos
    @LighterDos 6 месяцев назад

    Спасибо! Очень понятно и доходчиво, супер

  • @sergeytsoy9447
    @sergeytsoy9447 6 месяцев назад

    Когда один пример стоит миллионов объяснений

  • @tapin13
    @tapin13 6 месяцев назад

    👍

  • @fairo001
    @fairo001 6 месяцев назад

    Добрый день. Спасибо за видео. Предлагаю идею следующей итерацией переделать на project loom

    • @petrelevich
      @petrelevich 6 месяцев назад

      Да, это тоже есть в планах. Для сервера будет практическое применение, и в нем будут применены новые потоки.

  • @webbnba
    @webbnba 6 месяцев назад

    Продолжайте, толковый материал. Спасибо!

  • @wildjoe6259
    @wildjoe6259 6 месяцев назад

    Спасибо!

  • @botcser
    @botcser 6 месяцев назад

    Странно, вроде видео про применение gRPC, а кучу времени ушло на рассказ, как лучше работать со sleep или git... при том, что основную вещь "что такое setNumber(value)" не раскрыл

  • @watchman3676
    @watchman3676 6 месяцев назад

    Лекция хорошая, но есть вопрос. Почему в build.gradle одни параметры выделены белым цветом, а другие серым и подчеркнуты?

    • @petrelevich
      @petrelevich 6 месяцев назад

      Idea так подсвечивает синтаксис

    • @watchman3676
      @watchman3676 6 месяцев назад

      @@petrelevich Отличный ответ)) Я то думал, что, Идея подчеркивает разным цветом используемые и не используемые переменные, простые типы и классы и т.д. А оказывается это просто синтаксис без особого смысла))

  • @Wansery
    @Wansery 8 месяцев назад

    Хоть с темой знаком, но всё равно смог узнать для себя что-то новое)

  • @bulanovdms
    @bulanovdms 8 месяцев назад

    Сергей, здравствуйте. Подскажите пожалуйста, какие преимущества использовать outbox подход вместо встроенных транзакций кафки (KIP-98)

    • @petrelevich
      @petrelevich 8 месяцев назад

      Я про это говорил в 9:18. Встроенные транзакции работают при перекладывании сообщения из топика в топик. Я рассматриваю ситуацию с одним топиком.

  • @user-ok3xn3vx3h
    @user-ok3xn3vx3h 8 месяцев назад

    Спасибо, даже спустя два года все актуально)

  • @chaywithlemon
    @chaywithlemon 8 месяцев назад

    Автору канала спасибо за труд, только один момент довольно сильно раздражает, перед каждым словом чавкать и произносить букву А, прочтите что-нибудь про ораторское искусство или о лексикографий, или что-то из преподавательской деятельности в целом, у вас не должно быть таких задержек и раздражающих привычек чтобы у слушателей не было таких ощущений, спасибо