Нейросети. Финальная часть.
Для коллег-дизайнеров ситуация тоже вполне стабильная. MidJourney генерирует красивые и качественные картинки, но…
1. Все результаты растровые;
2. Иногда бывают артефакты;
3. Плохо генерирует текст;
4. UI элементы – без комментариев.
Суммируя эти нюансы, можно смело сказать, что между нейросетью и разработчиком все равно должен быть дизайнер, который подготовит графику должным образом. Верстать растр – сплошная боль, равно как и вносить в него правки. Картинки с артефактами нужно дорабатывать руками. Картинку с нужным вам текстом вы вообще вряд ли сгенерируете.
Нейронки-художники будут полезны для создания референсов и черновиков. Заказчик может сгенерировать примерный результат, который он хочет увидеть у себя в проекте, и показать его дизайнеру. А дизайнеры могут генерировать черновые примеры с минимумом усилий.
Да, есть узко направленные нейронки типа LOOKA, которые снижают стартовые затраты бизнеса, но это не замена дизайнеров. Генераторы логотипов, так же, как и конструкторы сайтов и no code решения существуют уже давно, но никто не предрекал вымирание профессий из-за подобных сервисов.
Резюмируя весь цикл постов: нейросети в текущем виде, определенно, изменят многие рабочие сферы. Внедрение нейронок в рабочий процесс повышает продуктивность и конкурентоспособность тех, кто идет в ногу со временем. В то время как те, кто сопротивляется прогрессу, будут постепенно вытесняться первыми. И это касается не только людей, но и компаний. Notion, Quizlet, Microsoft, поисковики типа you.com или perplexity.ai и многие другие сервисы уже используют технологии OpenAI, и это только начало.
А что вы думаете о хайпе вокруг нейронок?
Для коллег-дизайнеров ситуация тоже вполне стабильная. MidJourney генерирует красивые и качественные картинки, но…
1. Все результаты растровые;
2. Иногда бывают артефакты;
3. Плохо генерирует текст;
4. UI элементы – без комментариев.
Суммируя эти нюансы, можно смело сказать, что между нейросетью и разработчиком все равно должен быть дизайнер, который подготовит графику должным образом. Верстать растр – сплошная боль, равно как и вносить в него правки. Картинки с артефактами нужно дорабатывать руками. Картинку с нужным вам текстом вы вообще вряд ли сгенерируете.
Нейронки-художники будут полезны для создания референсов и черновиков. Заказчик может сгенерировать примерный результат, который он хочет увидеть у себя в проекте, и показать его дизайнеру. А дизайнеры могут генерировать черновые примеры с минимумом усилий.
Да, есть узко направленные нейронки типа LOOKA, которые снижают стартовые затраты бизнеса, но это не замена дизайнеров. Генераторы логотипов, так же, как и конструкторы сайтов и no code решения существуют уже давно, но никто не предрекал вымирание профессий из-за подобных сервисов.
Резюмируя весь цикл постов: нейросети в текущем виде, определенно, изменят многие рабочие сферы. Внедрение нейронок в рабочий процесс повышает продуктивность и конкурентоспособность тех, кто идет в ногу со временем. В то время как те, кто сопротивляется прогрессу, будут постепенно вытесняться первыми. И это касается не только людей, но и компаний. Notion, Quizlet, Microsoft, поисковики типа you.com или perplexity.ai и многие другие сервисы уже используют технологии OpenAI, и это только начало.
А что вы думаете о хайпе вокруг нейронок?
👍6❤2🔥2💩1
Задача: Преобразование отсортированного массива в двоичное дерево поиска
С прошлой алгоритмической задачей по деревьям у некоторых были трудности. Ловите еще одну, попроще.
Дан целочисленный массив
АВЛ-дерево — сбалансированное по высоте двоичное дерево поиска: для каждой его вершины высота её двух поддеревьев различается не более чем на 1.
P.S. В телеге проблематично оформить наглядный пример деревьев с картинками. Кому нужны картинки – переходите к статье с ответом. Раздел до "Решения" не содержит спойлеров.
Пример 1:
Ввод: nums = [-10,-3,0,5,9]
Вывод: [0,-3,9,-10,null,5]
Объяснение: [0,-10,5,null,-3,null,9] тоже подходит
Пример 2:
Ввод: nums = [1,3]
Вывод: [3,1]
Объяснение: [1,null,3] и [3,1] тоже АВЛ деревья.
Пишите свои версии в комментариях.
Ответ с объяснением 👈
#algorithms
С прошлой алгоритмической задачей по деревьям у некоторых были трудности. Ловите еще одну, попроще.
Дан целочисленный массив
nums
, элементы которого отсортированы по возрастанию. Преобразуйте его в сбалансированное по высоте двоичное дерево поиска (АВЛ-дерево).АВЛ-дерево — сбалансированное по высоте двоичное дерево поиска: для каждой его вершины высота её двух поддеревьев различается не более чем на 1.
P.S. В телеге проблематично оформить наглядный пример деревьев с картинками. Кому нужны картинки – переходите к статье с ответом. Раздел до "Решения" не содержит спойлеров.
Пример 1:
Ввод: nums = [-10,-3,0,5,9]
Вывод: [0,-3,9,-10,null,5]
Объяснение: [0,-10,5,null,-3,null,9] тоже подходит
Пример 2:
Ввод: nums = [1,3]
Вывод: [3,1]
Объяснение: [1,null,3] и [3,1] тоже АВЛ деревья.
Пишите свои версии в комментариях.
Ответ с объяснением 👈
#algorithms
👍7❤2🤔2🔥1
Атрибут translate='no': защита контента от автоматического перевода
Думаю, многие из вас используют Google translate в Chrome. Но бывает, что он "магическим" образом не переводит некоторый контент, а бывает, наоборот, переводит все подряд, из-за чего переведенная версия становится вырвиглазной. Для влияния на переводчик используется HTML атрибут translate="no". Этот элемент используется для обозначения того, что содержимое элемента не нужно переводить во время браузерного перевода страницы.
Бывает полезно, когда нужно запретить перевод:
- Служебных слов и фраз. Например, название компаний, товарные знаки и т.д;
- Кода и технических терминов – тут без комментариев;
- Адреса электронной почты, URL-адреса, и даты. Иногда переводчики могут некорректно обрабатывать подобные данные, искажая их значения.
Лично я встречался еще с одним кейсом: во время использования переводчика старая CRM система просто крашилась 😃. Проблема была в том, что переводчик заменял тэги, на которые у системы были ссылки. Думаю, случай достаточно редкий, т.к. система была очень старой и с кучей легаси.
@js_is_easy
Думаю, многие из вас используют Google translate в Chrome. Но бывает, что он "магическим" образом не переводит некоторый контент, а бывает, наоборот, переводит все подряд, из-за чего переведенная версия становится вырвиглазной. Для влияния на переводчик используется HTML атрибут translate="no". Этот элемент используется для обозначения того, что содержимое элемента не нужно переводить во время браузерного перевода страницы.
Бывает полезно, когда нужно запретить перевод:
- Служебных слов и фраз. Например, название компаний, товарные знаки и т.д;
- Кода и технических терминов – тут без комментариев;
- Адреса электронной почты, URL-адреса, и даты. Иногда переводчики могут некорректно обрабатывать подобные данные, искажая их значения.
Лично я встречался еще с одним кейсом: во время использования переводчика старая CRM система просто крашилась 😃. Проблема была в том, что переводчик заменял тэги, на которые у системы были ссылки. Думаю, случай достаточно редкий, т.к. система была очень старой и с кучей легаси.
@js_is_easy
👍15🔥4❤2
CSS модули. Композиция
Я еще в декабре делал ревью самых популярных подходов стилизации. Из статьи очевидно, что моим фаворитом являются CSS-модули.
Хочу разобрать несколько неочевидных моментов, на которых буксуют при переходе из нативного scss/css.
Начну с композиции (наследования). CSS-модули позволяют легко объединять и наследовать стили как из разных файлов, так и внутри одного файла, используя директиву composes. Замечу, что в отличие от @include утилиты в sass, которая тупо копипастит стили, здесь происходит именно объединение классов, т.е., если применить класс primary к компоненту, то к нему автоматически применится и класс base.
превратится в
Я еще в декабре делал ревью самых популярных подходов стилизации. Из статьи очевидно, что моим фаворитом являются CSS-модули.
Хочу разобрать несколько неочевидных моментов, на которых буксуют при переходе из нативного scss/css.
Начну с композиции (наследования). CSS-модули позволяют легко объединять и наследовать стили как из разных файлов, так и внутри одного файла, используя директиву composes. Замечу, что в отличие от @include утилиты в sass, которая тупо копипастит стили, здесь происходит именно объединение классов, т.е., если применить класс primary к компоненту, то к нему автоматически применится и класс base.
<div className={styles.primary} />
превратится в
<div class='primary_M4s71 base_6fsXP' />
@js_is_easy👍10🔥6❤3
CSS модули. Глобальные стили
CSS-модули автоматически генерируют уникальные имена классов для изоляции стилей. Однако, иногда может потребоваться применить глобальные стили. Например, изменить внешний класс или для компонента, которому нельзя присвоить дополнительный класс. Для этого используется ключевое слово
Второй вариант хорошо показывает себя, если нужно использовать какие-то старые компоненты, а основной код уже переехал на CSS-модули.
@js_is_easy
CSS-модули автоматически генерируют уникальные имена классов для изоляции стилей. Однако, иногда может потребоваться применить глобальные стили. Например, изменить внешний класс или для компонента, которому нельзя присвоить дополнительный класс. Для этого используется ключевое слово
:global
. Второй вариант хорошо показывает себя, если нужно использовать какие-то старые компоненты, а основной код уже переехал на CSS-модули.
@js_is_easy
👍8❤2🔥2
CSS модули. Вложенные селекторы
Простой, но не совсем очевидный момент – все классы, даже вложенные, в CSS модулях экспортируются плоским (один уровень вложенности) объектом. Допустим, есть класс
Конечно, было бы семантически удобнее использовать первый вариант, но имеем, что имеем. Если приложение спроектировано грамотно и компоненты разбиты на атомы, то иногда можно пренебречь семантикой (БЭМ) – сборщик подставит нужное имя в класс. Например, если в компоненте только кнопка, то классы
Кстати, на практике я редко использую вложенные селекторы. Думаю, что в CSS-модулях в них нет такой необходимости, как в нативном CSS. В примере с кнопкой можно вытащить
@js_is_easy
Простой, но не совсем очевидный момент – все классы, даже вложенные, в CSS модулях экспортируются плоским (один уровень вложенности) объектом. Допустим, есть класс
.button
, а внутри него классы .default
и .danger
. С такой структурой кажется логичным обращаться к вложенным классам типа styles.button.danger
, но в реальности к ним обращаются: styles.danger
.Конечно, было бы семантически удобнее использовать первый вариант, но имеем, что имеем. Если приложение спроектировано грамотно и компоненты разбиты на атомы, то иногда можно пренебречь семантикой (БЭМ) – сборщик подставит нужное имя в класс. Например, если в компоненте только кнопка, то классы
.button
и .danger
будут приемлемыми, а вот в сложных компонентах, например, с кнопкой и полем ввода стоит добавить больше семантики в модификаторы: .danger
→ .buttonDanger
и .inputDanger
, соответсвенно.Кстати, на практике я редко использую вложенные селекторы. Думаю, что в CSS-модулях в них нет такой необходимости, как в нативном CSS. В примере с кнопкой можно вытащить
.button
и .danger
на один уровень и семантика от этого не пострадает. В примере с кнопкой и полем ввода с семантикой еще проще – название блока уже заложено в класс, поэтому их можно вынести на один уровень и читаемость сохранится.@js_is_easy
👍9❤4🔥2
Задача: Самый повторяющийся элемент в массиве
Дан массив
Большой элемент – это элемент, который встречается более
Задание со звездочкой: Решите задачу за линейное время и используйте только
Первое решение, которое приходит на ум, довольно тривиальное: взять объект или
Пример 1:
Ввод: nums = [3,2,3]
Вывод: 3
Пример 2:
Ввод: nums = [2,2,1,1,1,2,2]
Вывод: 2
Пишите свои версии в комментариях.
Ответ с объяснением 👈
#algorithms
Дан массив
nums
размера n
, верните самый большой элемент.Большой элемент – это элемент, который встречается более
[n/2]
раз. Можете считать, что большой элемент всегда существует в массиве.Задание со звездочкой: Решите задачу за линейное время и используйте только
O(1)
памяти.Первое решение, которое приходит на ум, довольно тривиальное: взять объект или
Map
, пройтись циклом по массиву и записать количество каждого элемента, а потом пройтись циклом по этому объекту и найти элемент с максимальным значением. Решение рабочее, но может оказаться прожорливым на больших данных: память – O(N), время – O(N + M), где M – количество уникальных символов. В статье решение для условия со звездочкой.Пример 1:
Ввод: nums = [3,2,3]
Вывод: 3
Пример 2:
Ввод: nums = [2,2,1,1,1,2,2]
Вывод: 2
Пишите свои версии в комментариях.
Ответ с объяснением 👈
#algorithms
👍14❤2🔥2
Я сейчас занимаюсь переработкой и улучшением документации, в частности, DX гайдлайнов. И сегодня хочу поднять такую тему, как корпоративная архитектура. Данный пост больше о причинах, чем о конкретных практиках. По мере прогресса в работе я буду выкладывать прикладные советы.
Корпоративная архитектура обеспечивает структуру, управление и стандартизацию кодовой базы. Без корпоративной архитектуры проекты одной компании могут сильно отличаться друг от друга, даже если они написаны на одинаковом стеке. И это ведет к следующим проблемам:
Этот список можно продолжать и дальше, но все тезисы сводятся к тому, что без архитектуры увеличивается время и стоимость разработки, и уменьшаются довольство разработчиков и стабильность приложения.
Более прикладные советы будут в следующих постах, а резюмируя этот пост, я бы посоветовал обзавестись простой и короткой документацией, которая лежит на видном для всех месте и регулярно обновляется.
@js_is_easy
Корпоративная архитектура обеспечивает структуру, управление и стандартизацию кодовой базы. Без корпоративной архитектуры проекты одной компании могут сильно отличаться друг от друга, даже если они написаны на одинаковом стеке. И это ведет к следующим проблемам:
1.
Масштабируемость. Если заказчики захотят добавить одинаковый или похожий модуль в несколько проектов, то в каждом проекте разработчики будут изобретать свои велосипеды.2.
Коллаборация и поддержка. Когда разработчик переходит из одного проекта в другой, или просто временно подменяет кого-то, то переключение между проектами отнимает много ресурсов, а потом еще проблемы на ревью, т.к. у другой команды принято “по-другому”.3
. Повторное использование кода. Когда нет четких правил, где и что хранить, UI рано или поздно начинает смешиваться с логикой, и чтобы перенести компонент из одного проекта в другой, приходится его очищать от бизнес-логики.4
. Корпоративный набор библиотек. Здесь проблема, как во 2 и 3 пунктах вместе взятых, когда на каждом проекте свой зоопарк менеджеров, состояний и других взаимозаменяемых пакетов.Этот список можно продолжать и дальше, но все тезисы сводятся к тому, что без архитектуры увеличивается время и стоимость разработки, и уменьшаются довольство разработчиков и стабильность приложения.
Более прикладные советы будут в следующих постах, а резюмируя этот пост, я бы посоветовал обзавестись простой и короткой документацией, которая лежит на видном для всех месте и регулярно обновляется.
@js_is_easy
👍13❤4🤔2
Если рассматривать проблему коллаборации из предыдущего поста в рамках моей компании, то один из его пунктов заключался в том, что конфиги Eslint, prettier и TypeScript отличались от проекта к проекту иногда достаточно сильно. Для решения этой проблемы было решено вынести все конфиги в единое место.
Я создал монорепу с помощью lerna и добавил пакеты настроек линтеров и TS. Внутри пакетов ничего сверхъестественного: обычный package.json + соответствующий файл конфига (.eslintrc.js, prettier.config.js, tsconfig.json)
Дальше – конфиги подключаются довольно просто:
1. Устанавливаем пакеты в проект:
В результате получается, что все настройки линтеров спрятаны в пакеты, как и их зависимости. Например, в package.json проектов теперь нет явной зависимости eslint и его плагинов, все это содержится внутри пакета
Планируем добавить аналогичные общие конфиги для сборщиков и тестов (пока в процессе стандартизации).
P.S. Этот подход будет применен только к свежим и будущим проектам. Кардинальное изменение правил линтинга для старых проектов приведет к тому, что вся IDE будет светиться красным, а если исправлять эти ошибки, то испортится история коммитов.
P.P.S. Настройки можно наследовать и относительным путем. На случай, если у вас монорепа и выносить настройки в отдельный пакет нет желания.
@js_is_easy
Я создал монорепу с помощью lerna и добавил пакеты настроек линтеров и TS. Внутри пакетов ничего сверхъестественного: обычный package.json + соответствующий файл конфига (.eslintrc.js, prettier.config.js, tsconfig.json)
Дальше – конфиги подключаются довольно просто:
1. Устанавливаем пакеты в проект:
npm i @our-tools/eslint-config @our-tools/prettier-config @our-tools/ts-config
2. Наследуем каждый инструмент соответствующим образом (примеры на картинке). Я предпочитаю наследовать конфиги eslint и prettier в файле package.json. Да, это менее популярно, чем отдельные файлы, но, как показывает практика, желающих переопределить правила линтинга в файле package.json оказывается меньше 🤷♂️.В результате получается, что все настройки линтеров спрятаны в пакеты, как и их зависимости. Например, в package.json проектов теперь нет явной зависимости eslint и его плагинов, все это содержится внутри пакета
@our-tools/eslint-config
. Естественно, инфа по использованию конфигов прописана в хэндбуке и онбординг доке.Планируем добавить аналогичные общие конфиги для сборщиков и тестов (пока в процессе стандартизации).
P.S. Этот подход будет применен только к свежим и будущим проектам. Кардинальное изменение правил линтинга для старых проектов приведет к тому, что вся IDE будет светиться красным, а если исправлять эти ошибки, то испортится история коммитов.
P.P.S. Настройки можно наследовать и относительным путем. На случай, если у вас монорепа и выносить настройки в отдельный пакет нет желания.
@js_is_easy
👍11❤3🤔2
Стартовый шаблон
Еще одно решение, позволяющее организовывать разработку и поддерживать корпоративную архитектуру – это стартовый шаблон.
Реализация идеи довольно проста: создать проект-шаблон, включающий все базовые корпоративные зависимости, настройки и рекомендации, а затем форкать его для каждого нового проекта. Шаблон удобно обновлять и поддерживать. Проекты, основанные на этом шаблоне, можно обновлять путем мержа из шаблона.
Минус данного решения заключается в том, что оно не очень гибкое. Один шаблон – один тип проекта. Если активно развиваются не только основные приложения, но и виджеты, то придется обзавестись несколькими шаблонами, так как каждый тип проектов будет иметь свою специфику и зависимости. Например, самостоятельному приложению нужны зависимости react и react-router, а виджету - Storybook.
В качестве альтернативы можно рассмотреть генераторы, такие как Yeoman или Mustache.js (или даже их комбинацию с шаблонами). Они достаточно гибкие, но требуют больше времени на разработку и поддержку.
@js_is_easy
Еще одно решение, позволяющее организовывать разработку и поддерживать корпоративную архитектуру – это стартовый шаблон.
Реализация идеи довольно проста: создать проект-шаблон, включающий все базовые корпоративные зависимости, настройки и рекомендации, а затем форкать его для каждого нового проекта. Шаблон удобно обновлять и поддерживать. Проекты, основанные на этом шаблоне, можно обновлять путем мержа из шаблона.
Минус данного решения заключается в том, что оно не очень гибкое. Один шаблон – один тип проекта. Если активно развиваются не только основные приложения, но и виджеты, то придется обзавестись несколькими шаблонами, так как каждый тип проектов будет иметь свою специфику и зависимости. Например, самостоятельному приложению нужны зависимости react и react-router, а виджету - Storybook.
В качестве альтернативы можно рассмотреть генераторы, такие как Yeoman или Mustache.js (или даже их комбинацию с шаблонами). Они достаточно гибкие, но требуют больше времени на разработку и поддержку.
@js_is_easy
👍10❤2🔥2
Теперь вернемся на несколько уровней выше, к конкретным архитектурам.
Когда мы согласовывали корпоративную архитектуру, то рассматривали 3 варианта: Microfrontend через Module Federation, Atomic Design System и Feature Sliced Design. Старые проекты внутри себя уже были разделены на формальные модули, так что внедрение MF приняли единогласно, т.к. даже независимые деплои уже давали профит.
Однако сами по себе микрофронты никак не организуют код внутри модулей, поэтому нужно было решить, что внедрять дальше: ADS или FSD. На мой взгляд, FSD – отличная методология с самодостаточной философией и подходом, и я хотел протестировать ее на реальном проекте и понять все подводные, но… бэкграунд проектов сыграл свою роль:
1. Пара команд уже успешно внедрили ADS к себе в проекты в тестовом режиме.
2. С FSD ни у кого не было боевого опыта, поэтому переход мог быть достаточно долгим и болезненным.
3. Когда мы разрабатывали UI-кит, то договорились с дизайнерами, что они тоже будут следовать ADS методологии.
Да, ADS имеет свои недочеты, например, нет четкого соглашения, где хранить бизнес-логику и вспомогательные утилиты. На данный момент мы просто условились не спускать бизнес логику ниже уровня страниц, а универсальные утилиты переедут в отдельную внутреннюю репу с тулзами. Кстати, у нас UI-кит – это отдельная репа, и в MF приложениях, в большинстве случаев, почти не будет атомов, молекул и организмов. Они будут тянуться прямиком из кита.
Резюмируя, хочу сказать, что не надо внедрять что-либо просто потому что это сейчас модно. Сделайте анализ, оцените технический скилл и настрой команды, изучите бэкграунд проектов и потом принимайте решение.
P. S. Позже я планирую разобрать плюсы и минусы каждого подхода более подробно, а пока, те, кто заинтересован, переходите по соответствующим ссылкам в первом абзаце.
@js_is_easy
Когда мы согласовывали корпоративную архитектуру, то рассматривали 3 варианта: Microfrontend через Module Federation, Atomic Design System и Feature Sliced Design. Старые проекты внутри себя уже были разделены на формальные модули, так что внедрение MF приняли единогласно, т.к. даже независимые деплои уже давали профит.
Однако сами по себе микрофронты никак не организуют код внутри модулей, поэтому нужно было решить, что внедрять дальше: ADS или FSD. На мой взгляд, FSD – отличная методология с самодостаточной философией и подходом, и я хотел протестировать ее на реальном проекте и понять все подводные, но… бэкграунд проектов сыграл свою роль:
1. Пара команд уже успешно внедрили ADS к себе в проекты в тестовом режиме.
2. С FSD ни у кого не было боевого опыта, поэтому переход мог быть достаточно долгим и болезненным.
3. Когда мы разрабатывали UI-кит, то договорились с дизайнерами, что они тоже будут следовать ADS методологии.
Да, ADS имеет свои недочеты, например, нет четкого соглашения, где хранить бизнес-логику и вспомогательные утилиты. На данный момент мы просто условились не спускать бизнес логику ниже уровня страниц, а универсальные утилиты переедут в отдельную внутреннюю репу с тулзами. Кстати, у нас UI-кит – это отдельная репа, и в MF приложениях, в большинстве случаев, почти не будет атомов, молекул и организмов. Они будут тянуться прямиком из кита.
Резюмируя, хочу сказать, что не надо внедрять что-либо просто потому что это сейчас модно. Сделайте анализ, оцените технический скилл и настрой команды, изучите бэкграунд проектов и потом принимайте решение.
P. S. Позже я планирую разобрать плюсы и минусы каждого подхода более подробно, а пока, те, кто заинтересован, переходите по соответствующим ссылкам в первом абзаце.
@js_is_easy
👍9❤2🔥1
Ребята из iOS Такой 🍏 пригласили меня в гости на стрим. Мы из разных областей программирования, поэтому выбрали нейтральную тему для обсуждения: "Chat GPT и Нейронные сети".
Будем обсуждать прикладное использование нейронок в программировании и не только.
Залетайте в это воскресенье, 14 мая, в 18:00 по МСК на трансляцию.
P.S. Я еще в марте делал цикл постов про нейронки с лайфхаками. За это время набрался прикладного опыта и есть чем их дополнить.
@js_is_easy
Будем обсуждать прикладное использование нейронок в программировании и не только.
Залетайте в это воскресенье, 14 мая, в 18:00 по МСК на трансляцию.
P.S. Я еще в марте делал цикл постов про нейронки с лайфхаками. За это время набрался прикладного опыта и есть чем их дополнить.
@js_is_easy
Telegram
iOS Такой 🍏
Всем привет! Возвращаемся к Вам после выходных с новой прямой трансляцией!
В это воскресенье у нас круглый стол на тему "Chat GPT и Нейронные сети". Поговорим про полезность нейронок, ответим на вопросы и попытаемся порассуждать что будет дальше. А главным…
В это воскресенье у нас круглый стол на тему "Chat GPT и Нейронные сети". Поговорим про полезность нейронок, ответим на вопросы и попытаемся порассуждать что будет дальше. А главным…
👍7❤3🔥2🤮1
Страх писать негативные отчеты
Пока технические советы на стадии разработки, хотел бы затронуть важный психологический аспект.
Многие программисты боятся отчетов и стесняются задавать вопросы, особенно, если речь идет о сообщении проблем. Я не был исключением. Во время написания очередного отчета я боялся показаться некомпетентным или задать глупый вопрос. Но в какой-то момент я понял, что это только мешает мне и коллегам, а также ухудшает отношения с заказчиками.
Страх задавать вопросы ведет к снижению производительности, так как приводит к отсутствию обратной связи, которая необходима для общего прогресса и решения задач. Также страдает и личная мотивация. Страх говорить о проблемах может снизить чувство удовлетворения от работы, ведь новые задачи продолжают поступать, а нерешенные – накапливаться.
С точки зрения взаимоотношений с клиентами, недостаток прозрачности может привести к разочарованию с их стороны. Рано или поздно проблемы все равно обнаружатся и будет казаться, что вы пытались что-то скрыть.
Опытные менеджеры, с которыми я работал, говорили примерно следующее: "Если есть проблема, расскажи о ней, как можно раньше". Да, таракан внутри нас считает, что за плохие новости будет наказание, на практике же, все совсем иначе. Чем раньше вы поделитесь возникшей проблемой, тем быстрее сможете начать работать над ее решением.
Если вы боитесь задавать вопросы или сообщать о проблемах, помните – вы не одиноки. Это обычное чувство, с которым сталкиваются многие программисты. Но преодоление этого страха – важный шаг к улучшению собственной производительности, репутации и качества проектов.
Думаю, тимлиды и ПМы согласятся с тем, что создание культуры, в которой люди не боятся высказываться – важная часть успешного управления проектами.
Помните, что вопросы – это не знак некомпетентности. На самом деле, это признак профессионализма. Задавая вопросы, вы показываете, что заботитесь о качестве вашего продукта и вовлечены в разработку.
@js_is_easy
Пока технические советы на стадии разработки, хотел бы затронуть важный психологический аспект.
Многие программисты боятся отчетов и стесняются задавать вопросы, особенно, если речь идет о сообщении проблем. Я не был исключением. Во время написания очередного отчета я боялся показаться некомпетентным или задать глупый вопрос. Но в какой-то момент я понял, что это только мешает мне и коллегам, а также ухудшает отношения с заказчиками.
Страх задавать вопросы ведет к снижению производительности, так как приводит к отсутствию обратной связи, которая необходима для общего прогресса и решения задач. Также страдает и личная мотивация. Страх говорить о проблемах может снизить чувство удовлетворения от работы, ведь новые задачи продолжают поступать, а нерешенные – накапливаться.
С точки зрения взаимоотношений с клиентами, недостаток прозрачности может привести к разочарованию с их стороны. Рано или поздно проблемы все равно обнаружатся и будет казаться, что вы пытались что-то скрыть.
Опытные менеджеры, с которыми я работал, говорили примерно следующее: "Если есть проблема, расскажи о ней, как можно раньше". Да, таракан внутри нас считает, что за плохие новости будет наказание, на практике же, все совсем иначе. Чем раньше вы поделитесь возникшей проблемой, тем быстрее сможете начать работать над ее решением.
Если вы боитесь задавать вопросы или сообщать о проблемах, помните – вы не одиноки. Это обычное чувство, с которым сталкиваются многие программисты. Но преодоление этого страха – важный шаг к улучшению собственной производительности, репутации и качества проектов.
Думаю, тимлиды и ПМы согласятся с тем, что создание культуры, в которой люди не боятся высказываться – важная часть успешного управления проектами.
Помните, что вопросы – это не знак некомпетентности. На самом деле, это признак профессионализма. Задавая вопросы, вы показываете, что заботитесь о качестве вашего продукта и вовлечены в разработку.
@js_is_easy
👍9🔥5❤2
Заметки о forwardRef
В устаревшей доке React подробно описано, использование
1. Обратная совместимость. Когда React перешел с классов на функции (FC), единственным способом переписать компонент с рефом с класса на FC был
2. Соглашение о наименовании. В приложении, без классовых компонентов, вы можете передать реф в любом пропе (кроме специальных: ref или key), например,
3. Инкапсуляция. По умолчанию React не позволяет компоненту обращаться к узлам DOM других компонентов. Это сделано намеренно, чтобы разработчики не могли использовать любые компоненты в императивном стиле, а только те, которые были специально разработаны для этого. Рефы – это императивная лазейка в декларативном React. Используйте их только в крайнем случае, например, когда нужно напрямую обратиться к DOM.
В новой документации React есть отличная статья про рефы и о третьем пункте в частности: https://react.dev/learn/manipulating-the-dom-with-refs
P.S. Я в этом посте делился кастомным хуком для объединения внешних и локальных рефов. Забирайте.
@js_is_easy
В устаревшей доке React подробно описано, использование
forwardRef
. Но нет объяснений, зачем использовать этот HOC, когда можно просто передать ref
в пропсах. На это есть несколько причин:1. Обратная совместимость. Когда React перешел с классов на функции (FC), единственным способом переписать компонент с рефом с класса на FC был
forwardRef
. Это связано с тем, что в классах рефы привязывались к экземпляру класса, а у функций экземпляров нет. [Подробнее]. Если бы ref был в общем списке пропов, то при деструктуризации пропов он бы проваливался сразу дальше, а в классовых компонентах его обрабатывали отдельно.2. Соглашение о наименовании. В приложении, без классовых компонентов, вы можете передать реф в любом пропе (кроме специальных: ref или key), например,
innerRef
, и при этом в дочернем компоненте не нужно использовать forwardRef
. С точки зрения разработки, это проще и удобнее, так как требуется меньше HOC'ов. Однако если вы разрабатываете библиотеку или работаете в команде, то для других разработчиков может быть не очевидно, чем ваш innerRef отличается от общепринятого ref. Если вы планируете предоставить доступ к DOM верхнего элемента, делайте это через ref
. Если требуется доступ к другим элементам или императивный подход, можно добавить свои пропы для рефов (подробнее в следующем пункте).3. Инкапсуляция. По умолчанию React не позволяет компоненту обращаться к узлам DOM других компонентов. Это сделано намеренно, чтобы разработчики не могли использовать любые компоненты в императивном стиле, а только те, которые были специально разработаны для этого. Рефы – это императивная лазейка в декларативном React. Используйте их только в крайнем случае, например, когда нужно напрямую обратиться к DOM.
В новой документации React есть отличная статья про рефы и о третьем пункте в частности: https://react.dev/learn/manipulating-the-dom-with-refs
P.S. Я в этом посте делился кастомным хуком для объединения внешних и локальных рефов. Забирайте.
@js_is_easy
👍8❤2🤔1
String Manipulation [JetBrains][VS Code] – плагин, который поможет ускорить разработку. У него достаточно богатая функциональность, но лично я использую только смену регистра.
Эта фича экономит время, поскольку избавляет от необходимости вручную перепечатывать строки из одного регистра в другой. И, естественно, исключает опечатки.
Очень удобен при переименовании переменных во время деструктуризации данных на фронте с бэка из snake_case в camelCase и наоборот, а также при рефакторинге.
Естественно, можно настроить шорткаты, кнопка настроек на втором окне внизу.
#plugins
@js_is_easy
Эта фича экономит время, поскольку избавляет от необходимости вручную перепечатывать строки из одного регистра в другой. И, естественно, исключает опечатки.
Очень удобен при переименовании переменных во время деструктуризации данных на фронте с бэка из snake_case в camelCase и наоборот, а также при рефакторинге.
Естественно, можно настроить шорткаты, кнопка настроек на втором окне внизу.
#plugins
@js_is_easy
👍10❤5🔥3
Внезапно для себя обнаружил, что webpack, по дефолту, во время сборки пакета, делает NODE_ENV всегда равным mode. То есть, если вы собрали библиотеку в production режиме, установили ее в проект, запустили этот проект в режиме разработки (NODE_ENV=development), то при обращении к
Для проектов и большинства либ, типа UI компонентов, это не играет роли, а вот если в пакете есть проверки на окружение для оптимизаций в проде или, наоборот, расширенное логирование для разработки, то стоит обратить внимание на такую настройку вебпака, как optimization.nodeEnv. По дефолту, она делает
Имейте это ввиду, если разрабатываете какой-нибудь дев тулз. Я потратил пол дня, прежде чем понял, почему моя либа для отладки не работает в проекте😢
@js_is_easy
process.env.NODE_ENV
в проекте, значение будет development, а в установленной библиотеке – production.Для проектов и большинства либ, типа UI компонентов, это не играет роли, а вот если в пакете есть проверки на окружение для оптимизаций в проде или, наоборот, расширенное логирование для разработки, то стоит обратить внимание на такую настройку вебпака, как optimization.nodeEnv. По дефолту, она делает
NODE_ENV
всегда равной режиму сборки. А если присвоить ей значение false, то NODE_ENV
будет тянуться из окружения проекта.Имейте это ввиду, если разрабатываете какой-нибудь дев тулз. Я потратил пол дня, прежде чем понял, почему моя либа для отладки не работает в проекте
@js_is_easy
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🤯10❤3
Еще один интересный факт, связанный с вебпаком – это глобальная уникальность классов в CSS модулях. За их генерацию отвечает раздел modules в css-loader.
Допустим, есть два проекта с дефолтными настройками css-loader’а (localIdentName: "[path][name]__[local]--[hash:base64:5]
Я бы посоветовал добавлять в localIdentName название проекта или использовать localIdentHashSalt для избежания коллизий, если вы разрабатываете модули или UI библиотеки.
P.S. в create react app своя логика генерации классов, но эта проблема тоже присутствует.
@js_is_easy
Допустим, есть два проекта с дефолтными настройками css-loader’а (localIdentName: "[path][name]__[local]--[hash:base64:5]
).
В этих проектах есть два разных компонента, но с одинаковым путем: src/components/Footer/Footer.modules.scss
-> .container {…}
. Если собрать эти проекты, то в каждом билде будет класс: src-components-Footer-Footer-module__container--x3Zn_
. Эти классы уникальны в рамках одного проекта, но если соединить эти проекты через Module Federation или внешние зависимости, то получается неожиданный конфликт классов. Полагаю, что base64 использует в качестве сида путь до файла.Я бы посоветовал добавлять в localIdentName название проекта или использовать localIdentHashSalt для избежания коллизий, если вы разрабатываете модули или UI библиотеки.
P.S. в create react app своя логика генерации классов, но эта проблема тоже присутствует.
@js_is_easy
webpack
css-loader | webpack
webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
👍8❤3🤔3🔥2
Хотел в прошлом посте раскрыть тему умирающего CRA, но решил что он достоен отдельного.
Последний раз я создавал и сопровождал проект через CRA около 3-х лет назад. С тех пор избегаю CRA. По нескольким причинам:
Кастомизация конфига. Есть два варианта и оба такие себе. Первый – делать eject и копаться в лапше конфигов. Второй – использовать craco или react-app-rewired и снова лезть в кишки, но уже на гитхабе, чтобы написать свои патчи.
Гора скрытых зависимостей. Под капотом около 50 зависимостей и все в
Больше не поддерживается. Если v4 еще худо-бедно обновляли, то на v5 забили почти сразу. Последний релиз больше года назад, свыше 1.5к issues, примерно треть из них за последний год. С каждой новой версией ноды растет риск несовместимости со свежими либами.
Любой мидл соберет нормальный конфиг вебпака с нуля. Почитайте несколько статей, это куда быстрее и приятнее, чем потом вникать в дебри CRA.
P.S. Последнее время нахваливают Vite (тут и тут). Сборщик быстрый и интересный, но в большой проект я бы его не взял – еще сырой. Если хочется что-то кроме webpack, то голый rollup.js будет постабильнее.
@js_is_easy
Последний раз я создавал и сопровождал проект через CRA около 3-х лет назад. С тех пор избегаю CRA. По нескольким причинам:
Кастомизация конфига. Есть два варианта и оба такие себе. Первый – делать eject и копаться в лапше конфигов. Второй – использовать craco или react-app-rewired и снова лезть в кишки, но уже на гитхабе, чтобы написать свои патчи.
Гора скрытых зависимостей. Под капотом около 50 зависимостей и все в
dependencies
разделе, некоторые из них периодически ломаются. Не нужен jest или tailwind? Не переживай, CRA все равно их установит.Больше не поддерживается. Если v4 еще худо-бедно обновляли, то на v5 забили почти сразу. Последний релиз больше года назад, свыше 1.5к issues, примерно треть из них за последний год. С каждой новой версией ноды растет риск несовместимости со свежими либами.
Любой мидл соберет нормальный конфиг вебпака с нуля. Почитайте несколько статей, это куда быстрее и приятнее, чем потом вникать в дебри CRA.
P.S. Последнее время нахваливают Vite (тут и тут). Сборщик быстрый и интересный, но в большой проект я бы его не взял – еще сырой. Если хочется что-то кроме webpack, то голый rollup.js будет постабильнее.
@js_is_easy
👍9❤2🔥2🤔1
Задача: Объединение отсортированных массивов
Даны два целочисленных массива
Объедините
Функция не должна ничего возвращать, вместо этого нужно мутировать массив
Задача со звездочкой: Сможете придумать алгоритм, который работает за время O(m + n)?
Пример 1:
Ввод: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Вывод: [1,2,2,3,5,6]
Объяснение: Массивы, которые мы объединяем – [1,2,3] и [2,5,6].
Результат объединения –[1,2,2,3,5,6].
Пример 2:
Ввод: nums1 = [1], m = 1, nums2 = [], n = 0
Вывод: [1]
Объяснение: Массивы, которые мы объединяем – [1] и [].
Результат объединения – [1].
Пример 3:
Ввод: nums1 = [0], m = 0, nums2 = [1], n = 1
Вывод: [1]
Объяснение: Массивы, которые мы объединяем – [] и [1].
Результат объединения – [1].
Обратите внимание, что, так как m = 0, в nums1 нет элементов. 0 здесь только для того, чтобы гарантировать, что результат слияния может поместиться в nums1.
Пишите свои версии в комментариях.
Ответ с объяснением 👈
#algorithms
@js_is_easy
Даны два целочисленных массива
nums1
и nums2
, отсортированных в возрастающем порядке, и два целых числа m
и n
, представляющие количество элементов в nums1
и nums2
, соответственно.Объедините
nums1
и nums2
в один массив, отсортированный в возрастающем порядке.Функция не должна ничего возвращать, вместо этого нужно мутировать массив
nums1
. Для этого, nums1
имеет длину m + n
, где первые m
элементов обозначают те, которые должны быть объединены, а последние n
элементов установлены в 0 и должны быть проигнорированы. nums2
имеет длину n.Задача со звездочкой: Сможете придумать алгоритм, который работает за время O(m + n)?
Пример 1:
Ввод: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Вывод: [1,2,2,3,5,6]
Объяснение: Массивы, которые мы объединяем – [1,2,3] и [2,5,6].
Результат объединения –[1,2,2,3,5,6].
Пример 2:
Ввод: nums1 = [1], m = 1, nums2 = [], n = 0
Вывод: [1]
Объяснение: Массивы, которые мы объединяем – [1] и [].
Результат объединения – [1].
Пример 3:
Ввод: nums1 = [0], m = 0, nums2 = [1], n = 1
Вывод: [1]
Объяснение: Массивы, которые мы объединяем – [] и [1].
Результат объединения – [1].
Обратите внимание, что, так как m = 0, в nums1 нет элементов. 0 здесь только для того, чтобы гарантировать, что результат слияния может поместиться в nums1.
Пишите свои версии в комментариях.
Ответ с объяснением 👈
#algorithms
@js_is_easy
👍9❤4🔥3
Типы ответов в axios
Думаю, многие используют axios для запросов. Однако стоит помнить, что по умолчанию
Для большинства случаев, это именно то, что нужно. Но, например, если нужно скачать готовый файл, такое преобразование может сыграть коварную шутку. Axios преобразует ответ в текст (поскольку JSON невалиден), и при попытке создать из преобразованного ответа Blob, получим битый файл. Проблема в том, что на вкладке Network (Сеть) и при выводе в консоль, визуально, ответ не будет отличаться: и там, и там будет выглядеть, как набор символов – разница лишь в том, что в Network ответ еще не преобразован в строку.
Фиксится довольно просто, нужно в config передать
P.S. Имейте ввиду, что есть еще и другие типы ответов:
Думаю, многие используют axios для запросов. Однако стоит помнить, что по умолчанию
responseType
в нем установлен как json
. Это означает, что все ответы с сервера будут обрабатываться как JSON-объекты (или текст, если json битый).Для большинства случаев, это именно то, что нужно. Но, например, если нужно скачать готовый файл, такое преобразование может сыграть коварную шутку. Axios преобразует ответ в текст (поскольку JSON невалиден), и при попытке создать из преобразованного ответа Blob, получим битый файл. Проблема в том, что на вкладке Network (Сеть) и при выводе в консоль, визуально, ответ не будет отличаться: и там, и там будет выглядеть, как набор символов – разница лишь в том, что в Network ответ еще не преобразован в строку.
Фиксится довольно просто, нужно в config передать
responseType:
blob
, тогда axios будет обрабатывать ответ соответствующим образом.P.S. Имейте ввиду, что есть еще и другие типы ответов:
arraybuffer, document, text, stream.
@js_is_easy👍12🔥6❤3🍾1
Работа с Singleton'ами в Webpack Module Federation
При использовании библиотек, которые создают singleton для своей работы, необходимо быть особенно внимательными во время разработки своих либ или микрофрнтов.
Например, популярная либа для переводов, i18next, создает глобальный объект для всего приложения. Поскольку приложения на Module Federation часто шарят зависимости, то все они используют один объект. Следовательно, при стандартной инициализации конфигов в обоих приложениях, они будут конфликтовать (пример на скрине).
В react-i18next есть пара способов решения проблемы. Для начала в обоих случаях нужно создать новый экземпляр i18next, а затем:
1. Можно создать кастомный хук useTranslation для каждого приложения с перезаписанным экземпляром
2. Или, что более универсально, использовать I18nextProvider с новым экземпляром.
@js_is_easy
При использовании библиотек, которые создают singleton для своей работы, необходимо быть особенно внимательными во время разработки своих либ или микрофрнтов.
Например, популярная либа для переводов, i18next, создает глобальный объект для всего приложения. Поскольку приложения на Module Federation часто шарят зависимости, то все они используют один объект. Следовательно, при стандартной инициализации конфигов в обоих приложениях, они будут конфликтовать (пример на скрине).
В react-i18next есть пара способов решения проблемы. Для начала в обоих случаях нужно создать новый экземпляр i18next, а затем:
1. Можно создать кастомный хук useTranslation для каждого приложения с перезаписанным экземпляром
2. Или, что более универсально, использовать I18nextProvider с новым экземпляром.
@js_is_easy
👍9🔥3❤2