Chernyshoff ++
349 subscribers
139 photos
8 videos
48 links
Привет. Меня зовут Вячеслав Чернышов @v_chernyshoff, и я разработчик.

ʕっ•ᴥ•ʔっ

Когда-то я играл в театре и снимался в кино, но в 2016 увидел в соцсети рекламу курсов по программированию и открыл себя заново.

Сейчас я TechLead в СберТехе.
Download Telegram
↗️ Друзья! Во вторник в Рязани состоится митап (к сожалению, закрытый). Расскажу про репозиторные фреймворки. Сотрудникам Сбера можно подключиться онлайн ❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3❤‍🔥2
🌟 Большие гастроли SberProfi

Уже в этом месяце 4 ИТ-сообщества Сбера объединятся на рязанской площадке, чтобы выступить с крутыми хардовыми докладами и рассказать, что представляет собой проект профессиональных (и не только) сообществ и какую миссию в разрезе всего банка они выполняют.

Сообщества-миссионеры: профкомпетенционные Java, OPS, QA и продуктовое ЕФС.ФЛ.

Ниже – подробнее о том, что тебя ждёт ⚡️

Программа IT Community Day в Рязани

📌 14:30 – открытие

Ведущий:
Максим Журавлев, начальник управления (ИТ лидер) блока "Технологии",
ДИТ "Занять и Сберегать"

📌 14:40 – Спасаемся от Spring: есть ли альтернативы репозиторным фреймворкам?

Спикер:
Вячеслав Чернышов, Lead Java-разработчик,
СберТех

Немного о теме:

Какие могут быть альтернативы любимым многими и одновременно многими ненавидимым Spring Data JPA и Spring Data JDBC?
Ищём золотую середину! Мы возьмём основные фреймворки доступа к данным и проверим их на соответствие требованиям к репозиторным фреймворкам:
- контроль над запросами в базу данных со стороны разработчика;
- удобство для расширения функциональности и рефакторинга;
- соблюдения требований чистой архитектуры.
А потом посмотрим на альтернативы.

📌 15:25 – доклад-сюрприз от спикера из OPS Community! Повестка останется тайной вплоть до самого мероприятия 🤫

📌 16:10 – Автообновление продуктов в СБОЛе

Спикеры:
Вадим Баруткин, Middle Java-разработчик,
Руслан Платонов, Senior Java-разработчик,
ДИТ "Цифровые каналы B2C"

О чём расскажут:

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

📌 16:55 – Швейцарский нож автоматизации: бери нужное, оставляй лишнее

Спикер:
Владимир Михаленков, Middle Data-инженер,
Департамент данных и общих сервисов ИТ B2C

Подробнее о докладе:

Автоматизация тестов в больших компаниях всегда сталкивается с одним и тем же вызовом — технологическое многообразие. Разные языки, инструменты и подходы превращают работу в хаос: команды тратят время на переобучение, дублируют решения и снова изобретают велосипеды.
Как выйти из этого замкнутого круга? Один из ответов — создание унифицированного подхода к автоматизации: фреймворка или набора общих практик, которые объединяют лучшее из мира инструментов и снижают стоимость сопровождения.

☕️ 17:40 – кофе-брейк и активный нетворкинг со спикерами

🎤 18:10 – панельная дискуссия на тему "Сообщества – что за зверь такой, и зачем они компании?"

Ведущий:
Евгений Пьянзов, руководитель команды комьюнити-менеджеров,
Департамент технологического развития и координации деятельности

Эксперты панельки:

- Максим Журавлев, начальник управления (ИТ лидер) блока "Технологии",
ДИТ "Занять и Сберегать"

- Павел Юрченко, участник команды комьюнити-менеджеров,
Департамент технологического развития и координации деятельности

- Вадим Баруткин, Middle Java-разработчик,
ДИТ "Цифровые каналы B2C"

- Руслан Платонов, Senior Java-разработчик,
ДИТ "Цифровые каналы B2C"

- Секретный агент (не AI) от OPS Community 🥷

А чтобы дискуссия была жарче, буллеты панельки зрителям будет предложено сгенерировать самостоятельно 🔥

Тебя ждёт ламповый вечерок в кругу своих, знакомство с крутыми спикерами и экспертами и возможность проникнуться идеей сообществ и участия в их развитии - не пропусти! 🫂
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍3🥰1
В минувший четверг, друзья, в очередной раз убедился в величии русского балета. Пошёл на балет "Щелкунчик" в Большой театр по билету, подаренному Сбером, и был впечатлён уровнем мастерства. Даже поклоны были отдельным видом искусства.

Да, русский балет является нашей национальной гордостью, но почему так? Почему мы невероятно сильны в балете, но при этом крайне посредственны, например, в футболе? Как по мне, так отправить в нужном направлении мяч всяко легче, чем совершить тройной тулуп.

Мой опыт это подтверждает: 9 лет я занимался хореографией — сначала 6 лет в школьные годы, потом 3 года в театральном институте; мимолётный футбольный опыт тоже присутствует — за 10 дней съёмок "Гарпастума" я прошёл путь от "бью левой ногой в почти правильном направлении" до "могу начеканить мяч 30 раз".
Причину, по которой русский балет является лучшим в мире, а русский футбол, увы, нет, я вижу в объяснении притчи царя Соломона (22:29):

Видел ли ты человека, искусного в своём деле? Перед царями он будет стоять, а не перед простыми людьми.
Русский балет, в отличие от футбола, который был задуман как развлечение толпы, столетиями был развлечением знати. Представители высшего сословия, стараясь угодить двору, выпёстывали балет высшего качества, не считаясь с затратами — потом, кровью и слезами исполнителей. К началу XX века в лучших труппах Санкт-Петербурга и Москвы был выведен хореографический абсолют, импульс которого Большой и Мариинский театры держат до сих пор.

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

То есть, если балет создавали, чтобы представить его "перед царями", то футбол — чтобы поставить "перед простолюдинами", уж извините. С соответствующими критериями качества.

Окей. Как эта ценная информация поможет нам, разработчикам?, — вы спросите меня.

В разработке всё то же самое. Как и любая другая точка применения человеческих талантов, IT-проект имеет своей целью обслуживание интересов определённой целевой группы. И от стандартов этой группы зависит качество вашего труда.

Для кого вы пишете код, готовите свой доклад, проектируете систему? На какую целевую группу вы ориентируетесь в достижении результата?

Куда пойдут ваши решения? Станут ли они достоянием хорошего опенсорса — или сгинут в недрах мимолётного заказного проекта? Готовы ли вы защитить ваши идеи перед экспертным сообществом — или надеетесь, что их увидит исключительно ревьюер вашего PR? Готовы ли вы транслировать своё видение на большую аудиторию и быть "размазанным" профессиональным комьюнити?

Перед царями вы готовы стоять или перед простыми людьми?

И если потребительская планка слишком низкая, то стоит ли вообще потеть над результатом? Именно, что не стоит, но это будет маркером не ваших способностей, а низкой потребительской планки. То есть, когда вы выбираете себе планку, вы сразу выбираете свой профессиональный уровень.

Так, однажды один студент сказал мне: "Ну а зачем весь этот реактивный стек, виртуальные потоки и прочие приёмы для высокой нагрузки? Можно же найти себе простой проект и всю жизнь шлёпать CRUD-ы..."

Можно. Простые проекты не требовательны и вам не придётся напрягаться ни одного дня. Но потребительская планка ограничит и ваш профессиональный уровень. Вы будете прекрасно разбираться, как шлёпать CRUD-ы, но не более. А бывшие коллеги, которые пошли дальше и потратили силы и время, чтобы "стоять перед царями", со временем окажутся на недосягаемой от вас высоте.
👍6🔥5🍓4❤2🥰1
Коллеги из Spring АйО выложили перевод статьи Торбена Янсена и Теодора Ирхина "Как избежать распространенных ошибок при работе с JPA и Kotlin", правда, название перевели почему-то как "Почему Kotlin ломает JPA".

В качестве аргументов приводятся известные проблемы дизайна JPA, такие, как:

💥 Использование конструкторов по умолчанию.
💥 Открытость классов для наследования.


Эти проблемы дизайна JPA обычно преподносятся как "требования спецификации". Окей.

🤖 Дефолтные конструкторы. Что с ними не так.

Дефолтные конструкторы (особенно в data-классах) являются анти-паттерном. Data-класс создаётся с единственной целью положить в него данные. Возможно, какие-то поля придётся изменить (например, отвечающие за состояние сущности). Возможно, какие-то поля придётся проинициализировать позже. Но не бывает ситуации, когда вы создаёте data-класс, не имея данных ни для одного поля.

👉 Поэтому в Kotlin в data-классах нет дефолтных конструкторов. И это не работает с JPA.

Второе требование к классам с данными: поля по умолчанию должны быть иммутабельными. И в Kotlin это тоже заложено из коробки — если нужно сделать поле мутабельным, это нужно сделать специально. Придумано это для того, чтобы провоцировать разработчиков инициализировать сразу как можно больше полей (и избегать таким образом "временно‌й связности"). Ну а поскольку JPA сначала создаёт пустую сущность через дефолтный конструктор, а уж потом инициализирует поля через сеттеры, привет мутабельные поля там, где они идейно не нужны.

🤱 Открытость классов для наследования.

Второе принципиальное отличие Kotlin от Java в разрезе использования JPA: все классы final по умолчанию.

И это тоже правильно: в Effective Java предписывается не создавать классы открытыми для наследования без нужды, а если и создавать, то документировать это:

Item 19: Design and document for inheritance or else prohibit it.

В Java от любого класса можно унаследоваться by design. В Kotlin же классы по умолчанию закрыты от наследования. И это ограничение "ломает" JPA.

Не Kotlin "ломает" JPA. Kotlin был разработан с учётом опыта Java и с разумными ограничениями, которых в Java не хватает. JPA же проектировался с учётом известных архитектурных "свобод" Java и попросту ими пользуется. Особенности Kotlin JPA учитывать пытаются, но идёт непросто.

Кстати, Торбен Янсен забыл упомянуть о null-safety в Kotlin, которое тоже "ломает" JPA. "Ломает" ведь? 👹😏😁

Что до меня, то я по-прежнему люто ненавижу Hibernate / JPA вижу в JPA больше минусов, чем плюсов, о чём говорил в докладе на Spring NOW в марте прошлого года в Питере.
👍4🔥3❤2❤‍🔥1🤓1
Вчера упомянул временну‌ю связность, и поскольку термин не особо популярный, подозреваю, что не всем он оказался понятен. Поясню.

Временна‌я связность — это зависимость выполнения одного фрагмента кода от другого. Например:

val list = mutableListOf<String>()
list.add("abc")
list.removeAt(0)


Вторая и третья строчка кода связаны по времени. Если мы выполним их в обратном порядке,

val list = mutableListOf<String>()
list.removeAt(0)
list.add("abc")


то мы получим IndexOutOfBoundsException на второй строчке, поскольку элемента за индексом 0 пока нет. Это и есть временна‌я связность.

Очевидно, что количество таких временны‌х связей между инициализацией разных полей одной структуры данных должно стремиться к нулю.

Не очевидно? Давайте разберём.

💥 Первое и самое очевидное — это хрупкость

Если инициализация вашей сущности проходит красной нитью через всё приложение, любая попытка изменить код, которая затрагивает порядок операций, рискует всё сломать. Такую систему лучше не трогать, а просто ждать, пока она не станет Big Ball of Mud (большим комом грязи), а потом сжечь.

Хрупкость влияет и на тесты, которые проверяют теперь не только логику, но и скрытый временной контракт. Готовить такие тесты тяжело и неприятно: чтобы протестировать одну функцию, нужно воспроизвести целую цепочку зависимых друг от друга во времени инициализаций.

Про хрупкость в целом я рассказывал в статье про DDD, и из признаков плохой архитектуры он меня бесит больше всего.

💔 Второе — неявные контракты и нарушение SRP

Мы редко пишем документации. А без документации (да и с документацией тоже, чего уж тут) очень сложно понять, по какой причине в такой-то части приложения инициализируется такое-то поле. Мне приходилось работать с объектом, который частично инициализировался при получении из базы данных, частично — из данных, полученных по API из других сервисов, а частично — из результатов совмещения первых и вторых. Конечно, я не понимал логику инициализации всех полей этой сущности (и никто не понимал).

Такой класс к тому же начинает неявно управлять своим жизненным циклом и становится перегруженным, а это уже нарушение Принципа Единственной Ответственности (SRP).

👉 Ну и вдогонку: потенциальная свобода для race conditions

Если инициализация объекта растянута во времени и распределена по разным участкам кода, намного сложнее отслеживать ситуации, в которых возможен параллельный вызов двух функций, связанных временем (например, первая функция инициализирует состояние объекта, а вторая пытается его поменять). Идеальная почва для тяжёлых в воспроизведении плавающих багов.

⁉️ Что делать?

Лучший рецепт прост: если хотите избежать временной связности инициализации объекта, делайте такой объект иммутабельным. Такой объект должен быть готов к работе при первой же инициализации и присвоении ссылки на него и не иметь дефолтного конструктора.
👍2🥰2
Однажды я, только пришедший в одну команду, присутствовал на созвоне, посвящённом разбору утечки памяти. Местный сноб тогдашний техлид кластера долго и задумчиво изучал проблемный код, после чего сообщил собранию, что нужно убрать аннотацию Async с одного из методов.

Я взял слово и задал 2 вопроса:

❓ Почему этот метод вызывается в отдельном потоке?
❓ Из какого пула потоков эти потоки берутся?

И если на первый вопрос последовал вполне ожидаемый ответ в духе "не знаю и знать не хочу", то второй вопрос, судя по всему, поставил незадачливого техлида в тупик ☹️

И этому есть объяснение. Аннотацию Async в коде я видел, наверное, сотни раз. Но я ни разу не видел, чтобы для неё конфигурировали кастомный пул потоков. А значит, про такую возможность мало кто знает и о ней пора поговорить.

Если не управлять пулом потоков для методов, исполняемых асинхронно, то любой всплеск нагрузки с многократным вызовом такого метода может породить неограниченное количество потоков и действительно вызвать OutOfMemoryError. Для избежания подобных ситуаций мы можем задать пул, на потоках которого будет исполняться Async-метод (и только на них). За это отвечает единственный в аннотации Async параметр value:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Reflective
public @interface Async {

String value() default "";
}


Этот параметр и задаёт имя пула. Сам пул инициализируется в качестве Spring-бина и конфигурируется там же, например:

@Bean
fun specificTaskExecutor(): TaskExecutor = ThreadPoolTaskExecutor()
.also { executor ->
executor.corePoolSize = 10
executor.maxPoolSize = 20
executor.queueCapacity = 100
// executor.setVirtualThreads(true)
executor.setThreadNamePrefix("specific-thread-")
}


В этом примере мы законфигурировали всё самое нужное:

🟣 corePoolSize - базовое количество потоков
🟡 maxPoolSize - максимальное количество потоков на весь пул вообще
🔵 queueCapacity - ёмкость очереди ожидания

Также, можно сконфигурировать множество других опций, например, setVirtualThreads — сделать потоки виртуальными (но польза от этой опции весьма сомнительна).

После инициализации пула остаётся пометить им аннотацию:

@Async("specificTaskExecutor")
fun doSomethingSpecific() {
//бизнес-логика
}


И оп — теперь асинхронный метод работает в пределах заданного пула потоков. Пул ограничен 20 потоками (и 10 минимум). При этом, при всплесках нагрузки ожидающие задачи будут помещаться в BlockingQueue ёмкостью в 100 задач ✔️

В таких условиях получить OutOfMemoryError намного сложнее 🙂

P.S. @mipo256 подсказал, что corePoolSize - это не количество потоков на ядро, а базовое количество потоков. Поправил 🔁
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
This media is not supported in your browser
VIEW IN TELEGRAM
🔥3❤1
Java Conf в БКЗ Сбера на Кутузовском. Владимир Воскресенский зажигает про SberJDK 🔥
❤3
Возвращаясь к теме про асинхронные вызовы при помощи аннотации (спустя месяц, ха!). Есть ещё одно свойство таких вызовов, которого я ни разу не видел за 8 лет разработки. Угадайте, что это.

Не угадали? Я бы тоже не угадал.

Я ни разу не видел, чтобы метод, помеченный аннотацией Async, возвращал что-то кроме void. Да, этому есть причины: мы привыкли, что если мы выделяем отдельный поток для исполнения метода, значит, дальнейшая судьба его неизвестна и уж точно не повлияет на родительский поток. Ведь родительский поток побежит дальше, а выделенный поток завершит свою работу когда-нибудь потом. И тем не менее, такой вызов вполне может вернуть результат и с этим результатом можно работать.

Через CompletableFuture.

Давайте пример.

Как бы мы написали выполнение задачи в откреплённом потоке, не будь у нас под рукой аннотации Async? Думаю, что в максимально упрощённом виде это выглядело бы так (код максимально прост, поскольку его задача — показать пример максимально понятно и не перегружая логикой):


//наш метод, который надо выполнить
fun doSomething(delay: Long): Boolean = try {
//имитация работы
Thread.sleep(delay)
true
} catch (e: Exception) {
false
}

//отсюда дёргаем
@Test
fun processAsyncWithSupply() {
val futures = (0 until 10)
.map { it.toLong() }
.map { CompletableFuture.supplyAsync( { doSomething(it) }, specificTaskExecutor) }
CompletableFuture.allOf(*futures.toTypedArray()).join()

futures
.partition { it.getNow(false) }
.also { println("Result. Success: ${it.first.size}, failed: ${it.second.size}.") }
}


Мы выполнили метод doSomething в отдельном потоке из заданного пула, вернув CompletableFuture. Потом мы обработали CompletableFuture и дело с концом.

И такой пример подходит для ситуаций, когда мы не знаем, как именно нам нужно вызвать метод — в отдельном потоке или в том же. И если всегда в отдельном, то где-то мы можем забыть выделить поток.

Async же тем и хорош, что чётко декларирует выполнение метода в отдельном потоке.

С аннотацией Async пример при этом будет выглядеть так:


@Async("specificTaskExecutor")
fun doSomethingAsync(delay: Long): CompletableFuture<Boolean> = try {
//имитация работы
Thread.sleep(delay)
CompletableFuture.completedFuture(true)
} catch (e: Exception) {
CompletableFuture.completedFuture(false)
}

@Test
fun processAsyncDetached() {
val futures = (0 until 10)
.map { it.toLong() }
.map { doSomethingAsync(it) }
CompletableFuture.allOf(*futures.toTypedArray()).join()

futures
.partition { it.getNow(false) }
.also { println("Result. Success: ${it.first.size}, failed: ${it.second.size}.") }
}


Мы обеспечили безусловный вызов метода doSomethingAsync в отдельном потоке и вернули результат.

Код, кстати, рабочий, тесты можно позапускать. Но увлекаться не стоит — я вот, к примеру, позапускал — и пост вышел на месяц позже.


Какой вариант лучше?

Лично я обычно предпочитаю императивный код декларированию поведения через аннотации, но в данном случае намного важнее то, как этот метод будет использоваться. Если выполнение метода в отдельном потоке нужно заложить в контракт, нет ничего лучше аннотации Async. И тогда, если вам нужен результат, ComplatebleFuture подойдёт лучше всего.
👍5❤1🔥1
Залетел на митап по Kotlin, поучаствовал в дискуссии по поводу корутин 🤜🤛

Запись можно посмотреть в трансляции.
Forwarded from Java Community [Channel] (Sergey Karapetyan)
Уже завтра 10 июня ждем всех на Kotlin meetup.

Где пройдет мероприятие: Москва, Кутузовский проспект 32к1, 2 этаж, Конференц-зал

Программа:
🔹 17:30, Welcome coffee
🔹 18:00, "Кит на кот: выкидываем любимого ассистента, заменяем на Koog и экономим токены, нервы и время", Николай Поташников, Архитектор решений, член ПК Flow
🔹 18:45, "Tagless Final. Не спешите засорять бизнес-логику эффектами", Никита Петренко, Руководитель направления разработки Core Platform, SberDevices
🔹 19:30, Дискуссия: «Корутины: да или нет?», Александр Нозик (ведущий), Вячеслав Чернышов (СберТех), Александр Митропольский (СберИнвестиции), Александр Соколинский (Центр научного программирования)
🔹 20:00, Нетворкинг и фуршет

Онлайн участники могут присоединиться по ссылке. P.S. но всех очень ждем очно😎
Forwarded from Sber AI
ПЕРЕДАЁМ СЛОВО КОЛЛЕГЕ, КОТОРЫЙ ВЫ? 🫵😎

Вместо обычного поздравления с Днём программиста запускаем колесо обмена секретами среди звёзд этой профессии 🤩

⚠️ Осторожно: если рядом начальник, лучше слушать в наушниках


Начните обмен кружочками и в своих рабочих чатах!

❤️ — с праздником

✔️ Подписывайтесь на Sber AI в МАКС
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Sber AI
This media is not supported in your browser
VIEW IN TELEGRAM
Очень жаль, что коллега не знает разницы между тимлидом и техлидом, но с этим мы уже поделать ничего не можем 😏😁
😁5🔥1🥰1
Сегодня Сбер организует на Кутузовской довольно представительный Java-митап, на котором будут и Воскресенский, и Нозик, и Кулешов, и ваш покорный слуга. Можно прийти онлайн.
❤1
Forwarded from Java Community [Channel] (Sergey Karapetyan)
В этот четверг ждём всех на очном митапе в офисе Сбера🪩

Подробнее расскажем про программу:

16:30 — Сбор гостей и приветственный кофе‑брейк

17:00 — «От „Java тормозит“ до миллионов запросов: что происходит внутри JVM?», Владимир Воскресенский, Сбер

17:30 — «Spec Driven Development в мультирепозиторных проектах», Денис Баконин, Сбер

18:10 — «Дрессируем потоки. Добиваемся дешёвой конкурентности на JVM», Вячеслав Чернышов, СберТех

18:50 — «Специализированные агентские системы на Kotlin», Александр Нозик, Центр научного программирования

19:30 — Панельная дискуссия «Как меняется роль Java-разработчика под влиянием ИИ?»: Андрей Кулешов, Яндекс; Николай Пронников, Сбер; Владимир Воскресенский, Сбер; Сергей Пушкин, Альфа-Банк.

20:15 — Фуршет, нетворкинг, музыка🎛️

😎 Встречаемся 24 сентября в офисе Сбера (Кутузовский, 32).

Регистрация: https://developers.sber.ru/kak-v-sbere/events/java_meetup_2026
Мне попалось исследование Machine Human Intelligence Lab, учёные изучают Искусственный Интеллект и в данном материале они описывают когнитивную дивергенцию и петлю обратной связи делегирования применительно к ИИ и человеку.

Так вот. В 2017 контекстное окно нейросети составляло всего 512 токенов (примерно 200-300 слов). А в 2022 году, когда вышел ChatGPT 3.5 и произошёл Большой Взрыв нейросетей, их уже помещалось 4000, ну а сейчас 2 миллиона. Ну это понятно, нейросети развиваются. Но исследование не про нейросети, а про людей

Короче. Представим, что у человека тоже есть контекстное окно. Это объём информации, рассчитанный на основе метаанализа данных о скорости чтения и эмпирически обоснованного коэффициента масштабирования понимания, иными словами, это объём информации, который умещается в голове в рамках одной задачи, и его тоже можно посчитать в условных токенах. И размер этого контекстного окна тоже меняется. Угадайте, в какую сторону

В 2004 году оно составляло 16 000 токенов, в 2022 сравнялось с таковым для искусственного интеллекта (около 4 000), а сейчас, по оценкам, составляет 1 800 токенов. То есть, за 24 года объём информации, который мы способны держать в голове, сократился в 9 раз

На этом уже можно было бы остановиться, но нет. В работе также выдвигается гипотеза о петле обратной связи при делегировании. По мере развития Искусственного Интеллекта, снижается когнитивный порог, при котором люди делегируют задачи Искусственному Интеллекту, даже если задача требует минимальных умственных усилий. Оно и понятно, имея такой мощный костыль в виде ИИ, мы всё чаще и вовсе отказываемся думать

А вы что думаете?
🤔3👨‍💻1
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2❤1