From 1d9404032339c186bf6ef868b019a4961cedf9c3 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Fri, 23 Aug 2024 14:46:28 +0400 Subject: [PATCH 01/93] update main readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 02e7e309..a74a1eb1 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Перед тем как создавать pull request, изучите [требования к оформлению вопросов и ресурсов](./requirements.md). ## Статус -Сейчас программа находится в фазе активного переноса с прошлой платформы, где мы её писали (rizzoma.com), поэтому многие куски пока что ещё упущены, структура материала не окончательно заполнена. +Работы по основным направлениям завершены, а материалы активно используются нами и другими командами. На данный момент репозиторий активно поддерживается и развивается. Добавляются новые топики, обновляются и актуализируются старые. ## Градации Ниже приведены наши субъективные представления стандартных уровней мастерства разработчиков. From c949e1a22fbde13112a6fc15e86c4a5d786d7085 Mon Sep 17 00:00:00 2001 From: Ivan Tarasov Date: Fri, 23 Aug 2024 18:52:11 +0300 Subject: [PATCH 02/93] jun3/security: change xss link --- frontend/junior-3/security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/security.md b/frontend/junior-3/security.md index 646eae54..e15ecb49 100644 --- a/frontend/junior-3/security.md +++ b/frontend/junior-3/security.md @@ -25,7 +25,7 @@ ### Ресурсы -* [Основы XSS](https://hackware.ru/?p=1174&PageSpeed=noscript) +* [Основы XSS](https://hackware.ru/?p=1174) * [XSS](https://portswigger.net/web-security/cross-site-scripting) * [XSS Game](https://xss-game.appspot.com/level1) * [CSRF](https://portswigger.net/web-security/csrf) From 1775ada41abc2ce07880c7bcf5f2dbbeb5215a72 Mon Sep 17 00:00:00 2001 From: tangopj Date: Tue, 27 Aug 2024 15:34:58 +0600 Subject: [PATCH 03/93] fix: fixed the link --- shared/junior-1/testing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/junior-1/testing.md b/shared/junior-1/testing.md index 31bca5bd..ae233143 100644 --- a/shared/junior-1/testing.md +++ b/shared/junior-1/testing.md @@ -17,4 +17,4 @@ * [Зачем нужны юнит-тесты](https://tproger.ru/translations/unit-tests-purposes/) * [Как, используя TDD, сократить время разработки](https://www.simbirsoft.com/blog/razrabotka-cherez-testirovanie-polza-i-vred/) * [Об использовании модульных тестов и TDD](https://eax.me/unit-testing/) -* [Осторожно! Возможны побочные эффекты](http://blog.csssr.ru/2017/10/07/side-effects) +* [Осторожно! Возможны побочные эффекты](https://blog.csssr.com/ru/article/side-effects/) From d784398c1bf09d430308f2d6f7c3bd3919b2f54c Mon Sep 17 00:00:00 2001 From: Everrest1 Date: Fri, 30 Aug 2024 11:44:16 +0300 Subject: [PATCH 04/93] Add jun-3 seo section --- frontend/junior-3/README.md | 1 + frontend/junior-3/seo.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 frontend/junior-3/seo.md diff --git a/frontend/junior-3/README.md b/frontend/junior-3/README.md index aa1717fe..9146a7ba 100644 --- a/frontend/junior-3/README.md +++ b/frontend/junior-3/README.md @@ -11,6 +11,7 @@ - [Тестирование](../../shared/junior-3/testing.md) - [Базовые принципы кодирования и проектирования](../../shared/junior-3/basicCodingAndDesignPrinciples.md) - [Литература](./books.md) +- [Основы SEO](./seo.md) ## Специфично для нашего стека diff --git a/frontend/junior-3/seo.md b/frontend/junior-3/seo.md new file mode 100644 index 00000000..35eebfe1 --- /dev/null +++ b/frontend/junior-3/seo.md @@ -0,0 +1,34 @@ +# Основы SEO + +### Общие определения: + * Что такое seo? + * Что такое ранжирование? + * Что такое индексирование? + * Как работают поисковые роботы? Чем отличается поиск Яндекс и Google? + * Какие факторы влияют на позицию в поисковой выдаче? Какие шаги следует предпринимать для их оптимизации? + * Внешние факторы + * Коммерческие факторы + * Поведенческие факторы + * Как должна выглядеть идеальная seo-friendly структура сайта? + * Что такое нулевая позиция в выдаче? + * Какие есть способы поисковой оптимизации SPA? + +### Оптимизация на фронтенде: + * Какие html атрибуты, теги и метатеги, имеющие наибольшее влияние на ранжирование, вы знаете? + * Что такое Open Graph и как его использовать? + * Как сконфигурировать robots.txt и sitemap.xml и для чего? + * Как оптимизировать изображения? + * Как оптимизировать внутренние и внешние ссылки? + * Как добавить микроразметку? + * Какие особенности нужно учесть при вёрстке мобильной (адаптивной) версии? + * Рассказать о AMP и турбо-страницах + * Как искать и исправлять индексирование дублирующих страниц? Что произойдет, если этого не делать? + + +### Ресурсы + +* [Большая подборка материалов](https://habr.com/ru/articles/469139/) +* [Азы поисковой оптимизации для веб-разработчика](https://habr.com/ru/companies/selectel/articles/794146/) +* [SEO guide from developer’s perspective](https://medium.com/codeart-mk/seo-guide-from-developers-perspective-a142496b8cf8) +* [SPA SEO: A Single-Page App Guide to Google’s 1st Page](https://snipcart.com/blog/spa-seo) +* [Google и Yandex SEO оптимизация для SPA приложений](https://habr.com/ru/articles/778236/) From d5b6fd9f526e0b0f141c2779603ee7a00e31e9de Mon Sep 17 00:00:00 2001 From: Everrest1 Date: Mon, 2 Sep 2024 15:58:27 +0300 Subject: [PATCH 05/93] Add more detailed resources --- frontend/junior-3/seo.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/frontend/junior-3/seo.md b/frontend/junior-3/seo.md index 35eebfe1..eabc7685 100644 --- a/frontend/junior-3/seo.md +++ b/frontend/junior-3/seo.md @@ -9,9 +9,9 @@ * Внешние факторы * Коммерческие факторы * Поведенческие факторы + * Юзабилити * Как должна выглядеть идеальная seo-friendly структура сайта? * Что такое нулевая позиция в выдаче? - * Какие есть способы поисковой оптимизации SPA? ### Оптимизация на фронтенде: * Какие html атрибуты, теги и метатеги, имеющие наибольшее влияние на ранжирование, вы знаете? @@ -21,13 +21,31 @@ * Как оптимизировать внутренние и внешние ссылки? * Как добавить микроразметку? * Какие особенности нужно учесть при вёрстке мобильной (адаптивной) версии? - * Рассказать о AMP и турбо-страницах + * Что такое AMP и турбо-страницы? * Как искать и исправлять индексирование дублирующих страниц? Что произойдет, если этого не делать? - + * Какие есть способы поисковой оптимизации SPA? ### Ресурсы * [Большая подборка материалов](https://habr.com/ru/articles/469139/) + * [Как работает поиск Яндекса](https://yandex.ru/support/webmaster/yandex-indexing/site-indexing.html) + * [Подробное руководство по принципам работы Google Поиска](https://developers.google.com/search/docs/fundamentals/how-search-works?hl=ru&visit_id=638608767731277346-2134489696&rd=1) + * [Что такое структура сайта, как её создать и проанализировать](https://netpeaksoftware.com/ru/blog/site-structure-how-to-build-and-analyze-it) + * [Техническая оптимизация сайта, часть первая](https://vc.ru/seo/82301-tehnicheskaya-optimizaciya-saita-chast-pervaya) + * [Техническая оптимизация сайта, часть вторая](https://vc.ru/seo/83683-tehnicheskaya-optimizaciya-saita-chast-vtoraya) + * [Как создать и настроить карту сайта sitemap.xml в 2023 году](https://texterra.ru/blog/kak-sozdat-i-nastroit-kartu-sayta-sitemap-xml.html) + * [How to define robots.txt?](https://serpstat.com/blog/what-is-robotstxt-and-how-to-set-it-up-correctly/) + * [Что такое внутренние дубли страниц и как с ними бороться](https://netpeak.net/ru/blog/chto-takoye-vnutrenniye-dubli-stranits-i-kak-s-nimi-borot-sya/) + * [Как оптимизировать внутренние ссылки](https://serpstat.com/ru/blog/kak-optimizirovat-vnutrennie-ssylki/) + * [Внешняя оптимизация. Методы. Преимущества и недостатки](https://semantica.in/blog/vneshnyaya-optimizacziya-metody-preimushhestva-i-nedostatki.html) + * [Поведенческие факторы](https://blog.ingate.ru/seo-wikipedia/povedencheskie-faktory/) + * [Коммерческие факторы ранжирования](https://webmaster-seo.ru/seo/kommercheskie-faktory-ranzhirovaniya/) + * [Как провести анализ юзабилити текстов](https://serpstat.com/ru/blog/kak-provesti-analiz-juzabiliti-tekstov/) + * [13 приёмов оптимизации изображений: как выйти в топ поиска по картинкам](https://vc.ru/seo/74892-13-priemov-optimizacii-izobrazhenii-kak-vyiti-v-top-poiska-po-kartinkam) + * [Оптимизация для новичков: HTML-теги и атрибуты в SEO](https://netpeak.net/ru/blog/optimizatsiya-dlya-novichkov-html-tegi-i-atributy-v-seo/) + * [4 быстрых мобильных форматов: плюсы и минусы с точки зрения SEO](https://netpeaksoftware.com/ru/blog/5-quick-mobile-formats-pros-and-cons-from-an-seo-perspective) + * [Как оптимизировать сайт под Mobile-first index](https://netpeaksoftware.com/ru/blog/how-to-optimize-website-for-mobile-first-index) + * [Как оптимизировать сайт под голосовой поиск Google](https://netpeaksoftware.com/ru/blog/how-to-optimize-website-for-google-voice-search) * [Азы поисковой оптимизации для веб-разработчика](https://habr.com/ru/companies/selectel/articles/794146/) * [SEO guide from developer’s perspective](https://medium.com/codeart-mk/seo-guide-from-developers-perspective-a142496b8cf8) * [SPA SEO: A Single-Page App Guide to Google’s 1st Page](https://snipcart.com/blog/spa-seo) From 3e739d411c3bb3d1326acd9cd49ca0984472864d Mon Sep 17 00:00:00 2001 From: Everrest1 Date: Mon, 2 Sep 2024 16:02:12 +0300 Subject: [PATCH 06/93] Move topic before testing in list --- frontend/junior-3/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/README.md b/frontend/junior-3/README.md index 9146a7ba..b2bdbd54 100644 --- a/frontend/junior-3/README.md +++ b/frontend/junior-3/README.md @@ -8,10 +8,10 @@ - [DOM](./dom.md) - [Git](../../shared/junior-3/git.md) - [API](./api.md) +- [Основы SEO](./seo.md) - [Тестирование](../../shared/junior-3/testing.md) - [Базовые принципы кодирования и проектирования](../../shared/junior-3/basicCodingAndDesignPrinciples.md) - [Литература](./books.md) -- [Основы SEO](./seo.md) ## Специфично для нашего стека From 83f8d71f0e14c0cd01ae6bec798b05f86ef2a592 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Mon, 9 Sep 2024 14:37:17 +0400 Subject: [PATCH 07/93] add frotend-web3 theory and tasks (#411) --- frontend-web3/README.md | 12 ++ frontend-web3/basics.md | 86 +++++++++ frontend-web3/img/Screenshot_1.png | Bin 0 -> 30968 bytes frontend-web3/img/Screenshot_2.png | Bin 0 -> 48164 bytes frontend-web3/practice/1-send-erc-20.md | 30 ++++ frontend-web3/practice/2-mint-nft.md | 176 +++++++++++++++++++ frontend-web3/practice/how-to-IPFS.md | 48 +++++ frontend-web3/practice/test-erc-20-tokens.md | 47 +++++ 8 files changed, 399 insertions(+) create mode 100644 frontend-web3/README.md create mode 100644 frontend-web3/basics.md create mode 100644 frontend-web3/img/Screenshot_1.png create mode 100644 frontend-web3/img/Screenshot_2.png create mode 100644 frontend-web3/practice/1-send-erc-20.md create mode 100644 frontend-web3/practice/2-mint-nft.md create mode 100644 frontend-web3/practice/how-to-IPFS.md create mode 100644 frontend-web3/practice/test-erc-20-tokens.md diff --git a/frontend-web3/README.md b/frontend-web3/README.md new file mode 100644 index 00000000..a859ce4c --- /dev/null +++ b/frontend-web3/README.md @@ -0,0 +1,12 @@ +# Frontend Web3 + +Данный раздел посвящён разработке децентрализованных фронтенд приложений - dApp. Он предназначен для опытных фронтенд разработчиков, которые владеют глубокими знаниями в HTML, CSS, JS, изучили один из фреймворков (React или др.), и имеют несколько коммерческих проектов за своими плечами. Если вы новичок в веб-разработке, то вам сперва [сюда](../frontend/). + +## Теория + +* [Основы](./basics.md) + +## Практика + +* [Send ERC-20 (базовый уровень)](./practice/1-send-erc-20.md) +* [Mint NFT (продвинутый уровень)](./practice/2-mint-nft.md) \ No newline at end of file diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md new file mode 100644 index 00000000..1c46888d --- /dev/null +++ b/frontend-web3/basics.md @@ -0,0 +1,86 @@ +# Основы Web3 + +### Блокчейн +* Что такое Web1, Web2 и Web3? +* Что такое блокчейн? +* Что такое dApp? +* Что такое ethereum? +* Что такое evm-совместимые сети? +* Что такое тестовые сети (testnets)? +* Что такое газ? От чего зависит стоимость транзакций в блокчейне? +* Что такое смарт-контракт и ABI? +* Что такое “события” в смарт контракте? + +##### Ресурсы + +* [Introduction to Web3](https://ethereum.org/en/web3/) +* [Блокчейн изнутри: как устроен биткоин](https://vas3k.blog/blog/blockchain/) +* [Как устроен Ethereum и смарт-контракты](https://vas3k.blog/blog/ethereum/) +* [What are EVM Compatible Blockchains?](https://blog.thirdweb.com/evm-compatible-blockchains-and-ethereum-virtual-machine/) +* [Тестовая сеть](https://academy.binance.com/ru/glossary/testnet) +* [Ethereum: Network fees](https://ethereum.org/en/gas/) +* [What is Ethereum Gas? (Examples + Easy Explanation)](https://www.youtube.com/watch?v=3ehaSqwUZ0s) +* [Anatomy of smart contracts: Events and logs](https://ethereum.org/en/developers/docs/smart-contracts/anatomy/#events-and-logs) +* [Solidity docs: Events](https://docs.soliditylang.org/en/v0.7.0/contracts.html#events) + +### Кошельки +* Что такое кошелек? Что такое private key и public key? Перечислите хотя бы 5 разных кошельков. +* Что такое WalletConnect? + +##### Ресурсы + +* [What Is a Crypto Wallet?](https://academy.binance.com/en/articles/crypto-wallet-types-explained) +* [What is a Cryptocurrency Wallet? (3 Types + Key Examples)](https://www.youtube.com/watch?v=SQyg9pyJ1Ac&t=3s) +* [How to Use WalletConnect](https://academy.binance.com/en/articles/how-to-use-walletconnect) [[RU](https://academy.binance.com/ru/articles/how-to-use-walletconnect)] + +### Токены +* Что такое ERC-20 и ERC-721? +* Что такое аппрув токена, зачем он нужен? +* Что такое decimals, зачем нужен? Почему это важно для работы dApp? Как узнать значение decimals? +* Что такое minting, burning, staking? +* Что такое стейблкоин? В чём отличия между фиатными и алгоритмическими стейблкоинами? + +##### Ресурсы + +* [An Introduction to ERC-20 Tokens](https://academy.binance.com/en/articles/an-introduction-to-erc-20-tokens) +* [Ethereum Token Standards Part-II (ERC721)](https://medium.com/coinmonks/ethereum-token-standards-part-ii-erc721-4a4a7cbd5c74) +* [Что такое апрувы токенов (Token Approvals)?](https://revoke.cash/ru/learn/approvals/what-are-token-approvals) +* Что такое decimals? Ответ от chat-gpt [тут](./img/Screenshot_1.png) и [тут](./img/Screenshot_2.png). И косвенный ответ [тут](https://ethereum.stackexchange.com/questions/134958/erc20-decimals-in-smart-contract). +* [Base mechanics: minting, burning, staking](https://github.com/fullstack-development/web3-roadmap/blob/main/defi/tokens/tokenomics/token_mechanics.md) +* [What are stablecoins, and how do they work?](https://www.youtube.com/watch?v=fdPmjHtQ5aM) + +### IPFS +* Что такое IPFS и при чём тут NFT? + +##### Ресурсы + +* [IPFS: Interplanetary file storage!](https://www.youtube.com/watch?v=5Uj6uR3fp-U) +* [Scaling Your NFT Project: A Beginner’s Guide to IPFS By Pinata](https://www.bueno.art/blog/pinata-ipfs-guide) +* [Storing NFTs on IPFS](https://blog.ipfs.tech/2021-04-05-storing-nfts-on-ipfs/) + +### Фронтенд +* Как прочесть информацию из блокчейна и при чём тут RPC? +* Что такое etherscan? +* Что такое TransactionReceipt? +* Что такое viem? Что такое ethers.js? +* Что такое wagmi? + * Рассказать про следующие хуки: + * useReadContract + * useReadContracts + * useWriteContract + * useWaitForTransactionReceipt + * useAccount + * useBalance + +##### Ресурсы + +* [Anatomy of smart contracts](https://ethereum.org/en/developers/docs/smart-contracts/anatomy/) +* [JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/).
*Стоит ознакомиться как минимум с вводной частью. По сути это то, как шлются запросы в блокчейн на самом низком уровне, то есть под капотом у всех библиотек и sdk, таких как web3.js, ethers.js, viem, alchemy sdk и множества других. Например у viem, на каждый метод в документации есть ссылка на функцию, которую viem вызывает под капотом у JSON-RPC API.* +* [Viem docs: Transaction Receipt](https://viem.sh/docs/glossary/terms#transaction-receipt) +* [Viem docs: waitForTransactionReceipt](https://viem.sh/docs/actions/public/waitForTransactionReceipt.html) +* [Wagmi docs](https://wagmi.sh/react/getting-started) + + +### Общие ресурсы + +* [Playlist web2 to web3](https://www.youtube.com/playlist?list=PLJz1HruEnenAf80uOfDwBPqaliJkjKg69) \ No newline at end of file diff --git a/frontend-web3/img/Screenshot_1.png b/frontend-web3/img/Screenshot_1.png new file mode 100644 index 0000000000000000000000000000000000000000..92ac5b807600cf7c62f2c6b43d5fa0b6d2847564 GIT binary patch literal 30968 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 literal 0 HcmV?d00001 diff --git a/frontend-web3/practice/1-send-erc-20.md b/frontend-web3/practice/1-send-erc-20.md new file mode 100644 index 00000000..f9d26726 --- /dev/null +++ b/frontend-web3/practice/1-send-erc-20.md @@ -0,0 +1,30 @@ +# Отправка ERC-20 + +Отправка ERC-20 токенов другому пользователю. + +**Примечание:** такое задание не встретится вам на реальных проектах, по скольку пересылать ERC-20 токены можно в интерфейсе любого кошелька. Но это самый быстрый и простой способ познакомиться с разработкой dApp и базовыми вещами, которые вам придётся делать на любом web3 проекте. + +## Какие навыки даст задание? + +- Базовые навыки по работе с кошельками. Подключение/отключение кошелька, смена сети. +- Базовые навыки по работе с смарт контрактами, в частности, ERC-20. Вызов методов на чтение и запись, использование ABI. +- Реализуете поддержку работы в нескольких сетях. +- Научитесь обрабатывать различные события при работе с блокчейном и отображать соответствующий интерфейс - результат вызова смарт контракта (успех или ошибка), результат действий пользователя с кошельком и др. + +## Тех. задание + +- У пользователя должна быть возможность отправить ERC-20 токены другому пользователю. +- Для этого пользователь может выбрать один из токенов по умолчанию или добавить любой другой токен, которого нет в списке по умолчанию. Таким образом он выбирает токен, который хочет отправить. Для основных сетей токены по умолчанию можно взять из [топ-10]((https://etherscan.io/tokens)), а для тестовых сетей мы задеплоили типичные [ERC-20 токены](./test-erc-20-tokens.md). +- Затем он должен указать адрес кошелька получателя и сумму, которую хочет отправить. После чего нажать на кнопку “Отправить”. +- Приложение должно работать в нескольких сетях, например Ethereum и Polygon. Разработку вести в соответствующих тестовых сетях. Смена тестовых сетей на основные должна происходить путём изменения одной переменной окружения в `.env` файле. + +## Тех. требования + +- Интерфейс приложения должен быть отзывчивым. Необходимо показывать различные лоадеры, состояния загрузок, уведомления об успешных или неуспешных действиях. +- В приложении должны быть учтены и обработаны все возможные ошибки, как с точки зрения интерфейса, так и с точки зрения работы с кошельками и смарт контрактами. +- Для работы с блокчейном рекомендуется использоваться [wagmi](https://wagmi.sh/) + [viem](https://viem.sh/). Для интерфейса подключения кошелька можно использовать одно из [сторонних решений](https://wagmi.sh/react/guides/connect-wallet#third-party-libraries). +- Для запросов в блокчейн использовать в качестве RPC провайдера [стороннего провайдера](https://wagmi.sh/core/api/transports/http), а не публичные RPC URL. Например, Alchemy, RPC URL которого можно получить в [личном кабинете](https://dashboard.alchemy.com/). + +## Смарт контракт + +Отдельного смарт контракта для реализации данного функционала не требуется. Стандарт ERC-20 подразумевает наличие некоторого поведения и методов по умолчанию, которых нам достаточно. В частности такие методы как `transfer`, `approve`, `balanceOf` и другие, есть у любого ERC-20 токена. Вы можете импортировать стандартное ABI для всех ERC-20 токенов из viem - `import { erc20Abi } from 'viem';`. \ No newline at end of file diff --git a/frontend-web3/practice/2-mint-nft.md b/frontend-web3/practice/2-mint-nft.md new file mode 100644 index 00000000..cd6232b6 --- /dev/null +++ b/frontend-web3/practice/2-mint-nft.md @@ -0,0 +1,176 @@ +# Mint NFT + +Минтинг NFT коллекции + +**TODO: Добавить ссылку на контракт и гайд, как его задеплоить.** + +## Какие навыки даст задание? + +- Базовые навыки по работе с кошельками. Подключение/отключение кошелька, подпись сообщений. +- Базовые навыки по работе с смарт контрактами. Вызов методов на чтение и запись, использование ABI. +- Навыки работы с ERC-721. +- Навыки работы с функционалом администрирования на смарт-контракте. +- Навыки работы с деревом Меркла. +- Навыки работы с IPFS. +- Научитесь обрабатывать различные события при работе с блокчейном и отображать соответствующий интерфейс - результат вызова смарт контракта (успех или ошибка), результат действий пользователя с кошельком и др. + +## Тех. задание + +Необходимо выпустить свою коллекцию NFT. Пользователи смогут получить NFT из этой коллекции в 3 этапа - Airdrop, Private presale, Public sale. Необходимо реализовать: +1. Интерфейс минтинга NFT в 3 этапа для пользователей. +2. Административную панель для владельца продукта, который будет управлять этапами минтинга и whitelists. + +Каждый этап может быть в одном из 3х состояний - Soon, Available, Finished. Ограничений на очерёдность этапов нет. Теоретически все 3 этапа могут быть одновременно Available, этим будет управлять владелец продукта в админ панели. Но в базовом случае, очерёдность этапов следующая - Airdrop, Private presale, Public sale. + +- На этапе Airdrop счастливчики, которые попали в airdrop whitelist, смогут сминтить (mint) 2 NFT из коллекции бесплатно (заплатив только за газ). Для этого им нужно всего лишь нажать на кнопку mint на нашем сайте и подтвердить в кошельке транзакцию на минтинг двух NFT. Так же в админ панели, владелец продукта должен иметь возможность добавлять и убирать людей из airdrop whitelist. +- На этапе Private presale, другие счастливчики, которые попали в private presale whitelist, смогут купить до 3х NFT за более выгодную цену, чем на этапе Public Sale. Покупка происходит за нативную валюту сети (например для мейннета это ETH). Теперь пользователь может ввести количество NFT для покупки (не больше 3х) и нажать кнопку mint, с дальнейшим подтверждением транзакции в кошельке. Пользователь может купить токены на всём периоде действия этого этапа. То есть, если пользователь сначала купил 1 NFT, а через неделю вернулся и этап всё ещё доступен, он может докупить оставшиеся 2 NFT. Так же в админ панели, владелец продукта должен иметь возможность добавлять и убирать людей из private presale whitelist. +- На этапе Public sale, токены из NFT коллекции наконец сможет купить любой желающий, кто попадёт на наш сайт. Стоимость будет выше, чем на этапе Private presale, а ограничение количества NFT на одного пользователя станет 10 токенов. Пользователь также может купить токены на всём периоде действия этого этапа. +- На всю NFT коллекцию есть ограничение в 10000 токенов, которые могут быть сминчены пользователями. +- У пользователя должна быть возможность просмотреть все NFT из нашей коллекции, которые есть у него на кошельке. + +## Тех. требования + +- Интерфейс приложения должен быть отзывчивым. Необходимо показывать различные лоадеры, состояния загрузок, уведомления об успешных или неуспешных действиях. +- В приложении должны быть учтены и обработаны все возможные ошибки, как с точки зрения интерфейса, так и с точки зрения работы с кошельками и смарт контрактами. +- Для работы с блокчейном рекомендуется использоваться [wagmi](https://wagmi.sh/) + [viem](https://viem.sh/). Для интерфейса подключения кошелька можно использовать одно из [сторонних решений](https://wagmi.sh/react/guides/connect-wallet#third-party-libraries). +- Для запросов в блокчейн использовать в качестве RPC провайдера [стороннего провайдера](https://wagmi.sh/core/api/transports/http), а не публичные RPC URL. Например, Alchemy, RPC URL которого можно получить в [личном кабинете](https://dashboard.alchemy.com/). + + +## Смарт-контракт + +**TODO: Добавить ссылку на контракт и гайд, как его задеплоить.** + +Для реализации функционала, описанного выше, был разработан смарт-контракт. На реальном проекте вам необходимо будет общаться с разработчиком смарт контракта, что бы он вам рассказал как и что работает. Но в данном задании, для вашего удобства, ниже представлено описание некоторых методов этого смарт контракта на чтение и запись. + +### Работа с ролями + +У владельца продукта должна быть возможность управлять этапами продаж NFT и вайтлистами через админ панель. Для этого на контракте был реализован классический, для смарт контрактов, функционал ролей. Есть следующие роли: + +- `DEFAULT_ADMIN_ROLE` - главная роль на контракте. Только аккаунты с этой ролью могут выдавать (`grantRole`) и забирать (`revokeRole`) роли на контракте. По умолчанию эта роль имеется у того, кто задеплоил контракт. +- `SELL_PHASE_MANAGER_ROLE` - роль, позволяющая вызывать методы по управлению фазами продаж. +- `WHITE_LIST_MANAGER_ROLE` - роль, позволяющая вызывать методы по управлению вайтлистами. +- `PRICE_MANAGER_ROLE` - роль, позволяющая вызывать методы по управлению ценами на этапах public и private. + +Каждой роли соответствует строка `bytes32`, узнать которую можно, вызвав соответствующий метод на контракте (`DEFAULT_ADMIN_ROLE`, `SELL_PHASE_MANAGER_ROLE` и т.д.). + +Методы на чтение: + +- `hasRole` - получает строку `bytes32` роли и адрес кошелька, проверяя наличие указанной роли у переданного кошелька. Возвращает булевое значение. + +Методы на запись может вызвать только адрес с `DEFAULT_ADMIN_ROLE`: + +- `grantRole` - выдаёт указанную роль (`bytes32`) на указанный адрес кошелька. +- `revokeRole` - забирает указанную роль (`bytes32`) у указанного адрес кошелька. +- `renounceRole` - позволяет отозвать роль у самого себя. + +### Работа с этапами продаж + +Этапами продаж может управлять только адрес с ролью `SELL_PHASE_MANAGER_ROLE`. У каждого этапа продаж может быть одно из 3х состояний - 0, 1, 2, где 0 - Soon, 1 - Available, 2 - Finished. + +Методы на чтение: + +- `airDrop` - состояние этапа airdrop, от 0 до 2. +- `whiteListSale` - состояние этапа private presale, от 0 до 2. +- `publicSale` - состояние этапа public sale, от 0 до 2. + +Методы на запись: + +- `toggleAirDrop` - переключает состояние этапа airdrop, принимает цифру от 0 до 2. +- `toggleWhiteListSale` - переключает состояние этапа private presale, принимает цифру от 0 до 2. +- `togglePublicSale` - переключает состояние этапа public sale, принимает цифру от 0 до 2. + +### Работа с вайтлистами и Merkle Tree + +Два из трёх этапа доступны только пользователем, которые попали в соответствующий whitelist. Управление вайтлистами будет происходить в админ панели при помощи дерева Меркла (Merkle Tree) и библиотеки `merkletreejs`. У админа должен быть простой интерфейс, в котором он сможет просто добавлять и удалять адреса из двух вайтлистов и устанавливать новый вайтлист на контракт. А под капотом будет происходить работа с деревом Меркла. + +Листья дерева в нашем случае - это захэшированные адреса кошельков пользователей при помощи функции `keccack256`. Создать дерево можно следующим образом: + +```ts +import { MerkleTree } from 'merkletreejs'; +import { keccak256 } from 'viem'; + +const merkleTree = new MerkleTree( + [ + '0x0000000000000000000000000000000000000000', // адреса кошельков + '0x0000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000', + ], + keccak256, + { hashLeaves: true, sortPairs: true }, +); +``` + +После чего необходимо получить корень дерева - `merkleTree.getHashRoot()` и вызвать соответствующий метод на контракте - `setMerkleRootAirDrop` или `setMerkleRootWhiteList`. Метод будет вызываться админом и таким образом, мы установим на контракт Root hash для каждого этапа, по которому контракт будет проверять, есть ли пользователь в вайтлисте или нет. + +Так же для того, что бы вызывать методы `claimAirdrop`, `whitelistMint`, `canClaimAirDrop` и `isWhiteListed` - вам понадобится передавать в них массив `proof`. Каждому листку дерева Меркла (каждому кошельку) соответствует свой массив `proof`. Получить его можно следующим образом - `merkleTree.getHexProof(keccak256(address))`. + +Так как дерево Меркла создаётся в админ панели, а массив `proof` необходимо использовать в основном приложении, то встаёт вопрос о том, где и как хранить массив `proof` для каждого адреса из вайтлиста. Так как у нас нет своей базы данных, то воспользуемся децентрализованным хранилищем - IPFS. Данные будут храниться в формате JSON в следующем виде: + +```json +{ + "airdrop": [ + { + "address": "0x0000000000000000000000000000000000000000", + "proof": [ + "0x00314e565e0574cb412563df634608d76f5c59d9f817e85966100ec1d48005c0", + "0x1ebaa930b8e9130423c183bf38b0564b0103180b7dad301013b18e59880541ae" + ] + }, + { + "address": "0x0000000000000000000000000000000000000000", + "proof": [ + "0xe9707d0e6171f728f7473c24cc0432a9b07eaaf1efed6a137a4a8c12c79552d9", + "0x1ebaa930b8e9130423c183bf38b0564b0103180b7dad301013b18e59880541ae" + ] + } + ], + "private": [...] +} +``` + +Таким образом в админ панели данные о массиве `proof` для каждого адреса будут загружаться в IPFS ([как загрузить в IPFS?](./how-to-IPFS.md)). А в основном приложении данные будут считываться из IPFS. После чего будет происходить поиск по `address` для конкретного адреса и соответствующий `proof` будет передаваться на контракт при вызове вышеупомянутых методов. + +Методы на чтение: + +- `getMerkleRootAirDrop` - возвращает Root hash для вайтлиста, который используется на этапе airdrop. +- `getMerkleRootWhiteList` - возвращает Root hash для вайтлиста, который используется на этапе private presale. +- `getMerkleProofs` - возвращает IPFS хэш, в котором должен лежать JSON файл с массивами `proof`. +- `canClaimAirDrop` - проверяет, есть ли указанный кошелёк в вайтлисте airdrop. +- `isWhiteListed` - проверяет, есть ли указанный кошелёк в вайтлисте private presale. + +Методы на запись: + +- `setMerkleRootAirDrop` - устанавливает Root hash для вайтлиста, который используется на этапе airdrop. Может вызвать только `WHITE_LIST_MANAGER_ROLE`. +- `setMerkleRootWhiteList` - устанавливает Root hash для вайтлиста, который используется на этапе private presale. Может вызвать только `WHITE_LIST_MANAGER_ROLE`. +- `setMerkleProofs` - устанавливает IPFS хэш, в котором будет лежать JSON файл с массивами `proof`. Может вызвать только `WHITE_LIST_MANAGER_ROLE`. + + +### Другие методы на чтение + +- `CAT` - строка `bytes32`, которую необходимо подписать пользователю перед вызовом метода `mint` на этапе public sale. Подробнее в описании метода `mint`. +- `MAX_AIRDROP_MINT` - максимальное количество NFT, которое можно получить на этапе airdrop. +- `MAX_WHITELIST_MINT` - максимальное количество NFT, которое можно получить на этапе private presale. +- `MAX_PUBLIC_MINT` - максимальное количество NFT, которое можно получить на этапе public sale. +- `MAX_SUPPLY` - максимальное количество NFT, которое могут сминтить все пользователи суммарно. +- `tokenURI` - возвращает ссылку на метаданные для указанного `tokenId`. Метаданные как правило хранятся на IPFS и содержат в себе различную информацию о конкретном токене - ссылку на картинку, описание, атрибуты и др. [Пример метаданных](https://ipfs.io/ipfs/QmNe7EebKaNuRoN2ov9nMuwHXQvXbYXCLM9W1nDBxnqLgL/1.json). +- `placeholderTokenUri` - возвращает ссылку на метаданные-заглушку, которая будет возвращаться для всех `tokenUri` до тех пор, пока `isRevealed === false`. +- `isRevealed` - состояние контракта, по умолчанию `false`. Пока `false`, все `tokenUri` будут возвращать `placheloderTokenUri`, то есть метаданные-заглушку. Когда станет `true`, `tokenUri` будет возвращать настоящие метаданные для каждого токена. Зачем это нужно? Представьте, что владелец продукта не хочет раскрывать пользователям, какие NFT они сминтили до тех пор, пока не пройдут все этапы минтинга. Для этого он может переключать состояние `isRevealed` и в нужный для себя момент раскрыть информацию о каждом сминченном токене всем пользователям. +- `allowedToClaimDropAmount` - количество NFT, которое пользователю осталось сминтить на этапе airdrop. +- `allowedToWhiteListMintAmount` - количество NFT, которое пользователю осталось сминтить на этапе private presale. +- `allowedToPublicMintAmount` - количество NFT, которое пользователю осталось сминтить на этапе public sale. +- `whiteListSalePrice` - стоимость покупки одной NFT на этапе private presale. +- `publicSalePrice` - стоимость покупки одной NFT на этапе public sale. +- `totalAirdropMint` - возвращает количество NFT, которое сминтил указанный адрес на этапе airdrop. +- `totalWhitelistMint` - возвращает количество NFT, которое сминтил указанный адрес на этапе private presale. +- `totalPublicMint` - возвращает количество NFT, которое сминтил указанный адрес на этапе public sale. +- `tokensOfOwner` - возвращает список ID токенов, которыми владеет указанный адрес. +- `totalSupply` - общее количество сминченных NFT. + +### Другие методы на запись + +- `setPlaceHolderUri` - устанавливает ссылку на метаданные-заглушку, которую будет возвращать `tokenUri` до тех пор, пока `isRevealed === false`. Может вызвать только `DEFAULT_ADMIN_ROLE`. +- `setTokenUri` - устанавливает ссылку на метаданные. Может вызвать только `DEFAULT_ADMIN_ROLE`. +- `toggleReveal` - переключает состояние `isRevealed` на противоположное (см. методы на чтение). Может вызвать только `SELL_PHASE_MANAGER_ROLE`. +- `claimAirdrop` - минтинг NFT на этапе airdrop. Принимает количество NFT и массив `proof`. Благодаря массиву `proof` контракт может проверить, есть ли пользователь в вайтлисте airdrop или нет. +- `whitelistMint` - покупка NFT на этапе private presale. Принимает количество NFT, нативный токен для оплаты, а так же массив `proof`. Благодаря массиву `proof` контракт может проверить, есть ли пользователь в вайтлисте private presale или нет. +- `mint` - покупка NFT на этапе public sale. Принимает количество NFT, нативный токен для оплаты, а так же сигнатуру подписи (`signature`). Сигнатуру подписи можно получить, подписав пользователем специальное сообщение. В нашем случае это строка `bytes32` слова `CAT` (см. методы на чтение). Данную строку необходимо прогнать через утилиту `toBytes` из `viem` и передать в метод `signMessage` из `wagmi`. Метод попросит пользователя подписать сообщение и после подписи вернёт сигнатуру, которую и необходимо передать в вызов `mint`. В итоге, пользователь сначала подписывает сообщение, а затем вызывается `mint`. \ No newline at end of file diff --git a/frontend-web3/practice/how-to-IPFS.md b/frontend-web3/practice/how-to-IPFS.md new file mode 100644 index 00000000..ce028efb --- /dev/null +++ b/frontend-web3/practice/how-to-IPFS.md @@ -0,0 +1,48 @@ +# Как загрузить данные в IPFS? + +Так как IPFS - это децентрализованное хранилище, то загружать и читать из него данные можно напрямую, а можно используя сторонние решения, которые предоставляют более удобный API. Можно воспользоваться одним из таких решений - [thirdweb](https://portal.thirdweb.com/typescript/v5). Сама по себе библиотека предоставляет много чего, но нас интересует только работа с IPFS. + +Заранее зарегистрируйтесь и в [личном кабинете](https://thirdweb.com/dashboard/settings/api-keys) получите clientId. + +```ts +import { createThirdwebClient } from 'thirdweb'; +import { download, upload } from 'thirdweb/storage'; + +const proofs = { // Объект с пруфами, будущий JSON файл + airdrop: [ + { + address: '0x0000000000000000000000000000000000000000', + proof: [ + '0x00314e565e0574cb412563df634608d76f5c59d9f817e85966100ec1d48005c0', + '0x1ebaa930b8e9130423c183bf38b0564b0103180b7dad301013b18e59880541ae', + ], + }, + { + address: '0x0000000000000000000000000000000000000000', + proof: [ + '0xe9707d0e6171f728f7473c24cc0432a9b07eaaf1efed6a137a4a8c12c79552d9', + '0x1ebaa930b8e9130423c183bf38b0564b0103180b7dad301013b18e59880541ae', + ], + }, + ], + private: [...], +}; + +const clientId = process.env.clientId; // ваш clientId, который нужно получить в личном кабинете, на сайте thirdweb +const client = createThirdwebClient({ clientId }); + +// загрузка в IPFS +const file = new File([JSON.stringify(proofs)], '1.json'); +const uri = await upload({ + client, + files: [file], +}); + +// После загрузки, полученный uri необходимо сохранить на контракте, вызвав метод setMerkleProofs. После этого можно будет в любой момент получить этот uri из контракта, вызвав метод getMerkleProofs и передать его в функцию download, как написано ниже. + +// получение данных из IPFS +const file = await download({ + client, + uri, +}); +``` \ No newline at end of file diff --git a/frontend-web3/practice/test-erc-20-tokens.md b/frontend-web3/practice/test-erc-20-tokens.md new file mode 100644 index 00000000..65e074d5 --- /dev/null +++ b/frontend-web3/practice/test-erc-20-tokens.md @@ -0,0 +1,47 @@ +# Тестовые ERC-20 токены + +У каждого нижеперечисленного токена можно вызвать метод claim, который отправит на ваш баланс 10000 токенов. + +## Sepolia + +ARB - [0xf300c9bf1A045844f17B093a6D56BC33685e5D05](https://sepolia.etherscan.io/address/0xf300c9bf1A045844f17B093a6D56BC33685e5D05#code) + +DAI - [0xA68ecAb53bdcFdC753378a088CfB29d42915617E](https://sepolia.etherscan.io/address/0xA68ecAb53bdcFdC753378a088CfB29d42915617E#code) + +DOGE - [0xd409ffeb2f2e9dB0A75483a6417776CD6D7Ce774](https://sepolia.etherscan.io/address/0xd409ffeb2f2e9dB0A75483a6417776CD6D7Ce774#code) + +LINK - [0x53BB015921600B6E4b373125B90143090F957d50](https://sepolia.etherscan.io/address/0x53BB015921600B6E4b373125B90143090F957d50#code) + +OP - [0x54d412Fee228E13A42F38bC760faEFfDFE838536](https://sepolia.etherscan.io/address/0x54d412Fee228E13A42F38bC760faEFfDFE838536#code) + +PEPE - [0x8903FE8C94F3b7db3482d53ccE000998d112cC7d](https://sepolia.etherscan.io/address/0x8903FE8C94F3b7db3482d53ccE000998d112cC7d#code) + +TRX - [0xd445682a9B9FE0aE4053056E005f9393413407e1](https://sepolia.etherscan.io/address/0xd445682a9B9FE0aE4053056E005f9393413407e1#code) + +USDT - [0x8aC43Ed0652168827FA3906577dD44e4819B11D1](https://sepolia.etherscan.io/address/0x8aC43Ed0652168827FA3906577dD44e4819B11D1#code) + +USDC - [0x85d30853B690eEfa87854f240a81b4621b13FDF8](https://sepolia.etherscan.io/address/0x85d30853B690eEfa87854f240a81b4621b13FDF8#code) + +WBTC - [0x8805B377F0a28846198e81120179C4Ca5c6D5318](https://sepolia.etherscan.io/address/0x8805B377F0a28846198e81120179C4Ca5c6D5318#code) + +## Polygon Amoy + +ARB - [0x34cd8b477eb916c1c4224b2FFA80DE015cCC671b](https://amoy.polygonscan.com/address/0x34cd8b477eb916c1c4224b2FFA80DE015cCC671b#code) + +DAI - [0x1519d41F48F3621bCd583aa646C95217F87D3A99](https://amoy.polygonscan.com/address/0x1519d41F48F3621bCd583aa646C95217F87D3A99#code) + +DOGE - [0x0de27cBf804F1665eBc2F927944f54aA70cB4fC1](https://amoy.polygonscan.com/address/0x0de27cBf804F1665eBc2F927944f54aA70cB4fC1#code) + +LINK - [0xaa79133956a0F53Ef774c5b0e302784caF4A8Cc2](https://amoy.polygonscan.com/address/0xaa79133956a0F53Ef774c5b0e302784caF4A8Cc2#code) + +OP - [0x8E4eCf56B8736A83CE17213187118231D3C06FFF](https://amoy.polygonscan.com/address/0x8E4eCf56B8736A83CE17213187118231D3C06FFF#code) + +PEPE - [0x0c02cb84eEF5f3EA61be9DfeC7F884dffc1fa6c0](https://amoy.polygonscan.com/address/0x0c02cb84eEF5f3EA61be9DfeC7F884dffc1fa6c0#code) + +TRX - [0xEe7356FB1362fD659D03892719d424Bd8D9D8f70](https://amoy.polygonscan.com/address/0xEe7356FB1362fD659D03892719d424Bd8D9D8f70#code) + +USDT - [0x0a6DFA1eEf85B94E7e753bA222A6AcF2aE6C1a8b](https://amoy.polygonscan.com/address/0x0a6DFA1eEf85B94E7e753bA222A6AcF2aE6C1a8b#code) + +USDC - [0x6fD3B0bfB19Dc9C02f79E1e6E32444A390842700](https://amoy.polygonscan.com/address/0x6fD3B0bfB19Dc9C02f79E1e6E32444A390842700#code) + +WBTC - [0x36Ea22735269Cb7AA2A931Dd871a73c0a9124f2B](https://amoy.polygonscan.com/address/0x36Ea22735269Cb7AA2A931Dd871a73c0a9124f2B#code) \ No newline at end of file From fe5f2ffbdbfdf20eecdc0cffb98994fcf8c9146e Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Wed, 11 Sep 2024 10:35:46 +0400 Subject: [PATCH 08/93] fix typo --- frontend-web3/basics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md index 1c46888d..05430ac7 100644 --- a/frontend-web3/basics.md +++ b/frontend-web3/basics.md @@ -75,7 +75,7 @@ ##### Ресурсы * [Anatomy of smart contracts](https://ethereum.org/en/developers/docs/smart-contracts/anatomy/) -* [JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/).
*Стоит ознакомиться как минимум с вводной частью. По сути это то, как шлются запросы в блокчейн на самом низком уровне, то есть под капотом у всех библиотек и sdk, таких как web3.js, ethers.js, viem, alchemy sdk и множества других. Например у viem, на каждый метод в документации есть ссылка на функцию, которую viem вызывает под капотом у JSON-RPC API.* +* [JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/).
*Стоит ознакомиться как минимум с вводной частью. По сути это то, как шлются запросы в блокчейн на самом низком уровне, то есть под капотом у всех библиотек и sdk, таких как web3.js, ethers.js, viem, alchemy sdk и множества других. Например, у viem на каждый метод в документации есть ссылка на функцию в JSON-RPC API, которую viem вызывает у себя под капотом.* * [Viem docs: Transaction Receipt](https://viem.sh/docs/glossary/terms#transaction-receipt) * [Viem docs: waitForTransactionReceipt](https://viem.sh/docs/actions/public/waitForTransactionReceipt.html) * [Wagmi docs](https://wagmi.sh/react/getting-started) From 656b3f1bd383feb3d83892d45a4908b036f53ea8 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Wed, 11 Sep 2024 16:40:51 +0400 Subject: [PATCH 09/93] add additional questions to web3-frontend --- frontend-web3/basics.md | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md index 05430ac7..a705f451 100644 --- a/frontend-web3/basics.md +++ b/frontend-web3/basics.md @@ -3,25 +3,41 @@ ### Блокчейн * Что такое Web1, Web2 и Web3? * Что такое блокчейн? +* Что такое транзакция? Что такое revert транзакции? Почему транзакция исполняется с задержкой? +* Что такое цифровая подпись? * Что такое dApp? * Что такое ethereum? * Что такое evm-совместимые сети? * Что такое тестовые сети (testnets)? * Что такое газ? От чего зависит стоимость транзакций в блокчейне? -* Что такое смарт-контракт и ABI? -* Что такое “события” в смарт контракте? ##### Ресурсы * [Introduction to Web3](https://ethereum.org/en/web3/) * [Блокчейн изнутри: как устроен биткоин](https://vas3k.blog/blog/blockchain/) +* [Ethereum docs: Transactions](https://ethereum.org/en/developers/docs/transactions/) +* [Digital Signatures on ethereum](https://github.com/fullstack-development/blockchain-wiki/blob/main/concepts/digital-signature-on-ethereum/README.md) * [Как устроен Ethereum и смарт-контракты](https://vas3k.blog/blog/ethereum/) * [What are EVM Compatible Blockchains?](https://blog.thirdweb.com/evm-compatible-blockchains-and-ethereum-virtual-machine/) * [Тестовая сеть](https://academy.binance.com/ru/glossary/testnet) * [Ethereum: Network fees](https://ethereum.org/en/gas/) * [What is Ethereum Gas? (Examples + Easy Explanation)](https://www.youtube.com/watch?v=3ehaSqwUZ0s) + +### Смарт-контракты +* Что такое смарт-контракт и ABI? +* Что такое “события” в смарт контракте? + * Что такое indexed параметры? +* В чем отличия функций view, pure, payable в смарт-контракте? +* Что такое keccak256 и для чего применяется? + +##### Ресурсы + * [Anatomy of smart contracts: Events and logs](https://ethereum.org/en/developers/docs/smart-contracts/anatomy/#events-and-logs) -* [Solidity docs: Events](https://docs.soliditylang.org/en/v0.7.0/contracts.html#events) +* [Solidity docs: Events](https://docs.soliditylang.org/en/v0.8.27/contracts.html#events) +* [Event argument indexing](https://github.com/fullstack-development/blockchain-wiki/blob/main/solidity/event-argument-indexing/README.md) +* [Solidity docs: State mutability](https://docs.soliditylang.org/en/v0.8.27/contracts.html#state-mutability) +* [What are Payable Functions in Solidity?](https://docs.alchemy.com/docs/solidity-payable-functions) +* [Keccak256](https://github.com/fullstack-development/blockchain-wiki/tree/main/concepts/keccak256) ### Кошельки * Что такое кошелек? Что такое private key и public key? Перечислите хотя бы 5 разных кошельков. @@ -36,8 +52,10 @@ ### Токены * Что такое ERC-20 и ERC-721? * Что такое аппрув токена, зачем он нужен? + * Как можно узнать количество токенов, разрешенных для управления сторонним адресом? * Что такое decimals, зачем нужен? Почему это важно для работы dApp? Как узнать значение decimals? -* Что такое minting, burning, staking? +* Что такое minting и burning? +* Что такое staking? * Что такое стейблкоин? В чём отличия между фиатными и алгоритмическими стейблкоинами? ##### Ресурсы @@ -60,6 +78,7 @@ ### Фронтенд * Как прочесть информацию из блокчейна и при чём тут RPC? +* Почему при работе с числами из блокчейна нельзя пользоваться обычным типом `number`? Какой тип использовать вместо `number`? * Что такое etherscan? * Что такое TransactionReceipt? * Что такое viem? Что такое ethers.js? @@ -70,7 +89,8 @@ * useWriteContract * useWaitForTransactionReceipt * useAccount - * useBalance + * useBalance +* Как можно слушать события на смарт контракте? Как получить историю событий? ##### Ресурсы @@ -79,6 +99,8 @@ * [Viem docs: Transaction Receipt](https://viem.sh/docs/glossary/terms#transaction-receipt) * [Viem docs: waitForTransactionReceipt](https://viem.sh/docs/actions/public/waitForTransactionReceipt.html) * [Wagmi docs](https://wagmi.sh/react/getting-started) +* [Viem docs: watchEvent](https://viem.sh/docs/actions/public/watchEvent) +* [Viem docs: getLogs](https://viem.sh/docs/actions/public/getLogs) ### Общие ресурсы From 183dbcc53b3ab09ea955a2d1edae59dfa0802860 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Thu, 12 Sep 2024 12:13:47 +0400 Subject: [PATCH 10/93] add additional questions to web3-frontend --- frontend-web3/basics.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md index a705f451..8a17ee53 100644 --- a/frontend-web3/basics.md +++ b/frontend-web3/basics.md @@ -40,7 +40,8 @@ * [Keccak256](https://github.com/fullstack-development/blockchain-wiki/tree/main/concepts/keccak256) ### Кошельки -* Что такое кошелек? Что такое private key и public key? Перечислите хотя бы 5 разных кошельков. +* Что такое account и wallet? В чём отличие между ними? Перечислите хотя бы 5 кошельков. +* Что такое private key и public key? * Что такое WalletConnect? ##### Ресурсы @@ -56,7 +57,10 @@ * Что такое decimals, зачем нужен? Почему это важно для работы dApp? Как узнать значение decimals? * Что такое minting и burning? * Что такое staking? -* Что такое стейблкоин? В чём отличия между фиатными и алгоритмическими стейблкоинами? +* Что такое стейблкоин? + * Какие бывают виды стейблкоинов? + * Что такое обеспечение стейблкоина? + * Какие самые популярные стейблкоины есть? ##### Ресурсы From 225826f1d9aeff5cedf51e4025f7d7b37ebeb078 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Thu, 12 Sep 2024 12:28:04 +0400 Subject: [PATCH 11/93] add resources to web3-frontend --- frontend-web3/basics.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md index 8a17ee53..10551e39 100644 --- a/frontend-web3/basics.md +++ b/frontend-web3/basics.md @@ -48,6 +48,7 @@ * [What Is a Crypto Wallet?](https://academy.binance.com/en/articles/crypto-wallet-types-explained) * [What is a Cryptocurrency Wallet? (3 Types + Key Examples)](https://www.youtube.com/watch?v=SQyg9pyJ1Ac&t=3s) +* [What's the difference between a wallet and an account?](https://support.metamask.io/ru/managing-my-wallet/using-metamask/whats-the-difference-between-a-wallet-and-an-account-/) * [How to Use WalletConnect](https://academy.binance.com/en/articles/how-to-use-walletconnect) [[RU](https://academy.binance.com/ru/articles/how-to-use-walletconnect)] ### Токены @@ -69,6 +70,7 @@ * [Что такое апрувы токенов (Token Approvals)?](https://revoke.cash/ru/learn/approvals/what-are-token-approvals) * Что такое decimals? Ответ от chat-gpt [тут](./img/Screenshot_1.png) и [тут](./img/Screenshot_2.png). И косвенный ответ [тут](https://ethereum.stackexchange.com/questions/134958/erc20-decimals-in-smart-contract). * [Base mechanics: minting, burning, staking](https://github.com/fullstack-development/web3-roadmap/blob/main/defi/tokens/tokenomics/token_mechanics.md) +* [Стейблкоины. Как привязывают и почему не отвязывается!?](https://habr.com/ru/companies/metalamp/articles/763538/) * [What are stablecoins, and how do they work?](https://www.youtube.com/watch?v=fdPmjHtQ5aM) ### IPFS From a7c2c25fa4f1c3857302f9235b25e1cc9cc5deab Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Thu, 12 Sep 2024 14:39:50 +0400 Subject: [PATCH 12/93] add questions to web3-frontend --- frontend-web3/basics.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md index 10551e39..1abf4862 100644 --- a/frontend-web3/basics.md +++ b/frontend-web3/basics.md @@ -52,9 +52,11 @@ * [How to Use WalletConnect](https://academy.binance.com/en/articles/how-to-use-walletconnect) [[RU](https://academy.binance.com/ru/articles/how-to-use-walletconnect)] ### Токены -* Что такое ERC-20 и ERC-721? +* Что такое ERC-20 и ERC-721? В чем отличие этих токенов от нативной валюты блокчейна? +* Что такое ERC-1155? * Что такое аппрув токена, зачем он нужен? * Как можно узнать количество токенов, разрешенных для управления сторонним адресом? +* Что такое permit? в чем его отличие от approve? * Что такое decimals, зачем нужен? Почему это важно для работы dApp? Как узнать значение decimals? * Что такое minting и burning? * Что такое staking? @@ -67,7 +69,10 @@ * [An Introduction to ERC-20 Tokens](https://academy.binance.com/en/articles/an-introduction-to-erc-20-tokens) * [Ethereum Token Standards Part-II (ERC721)](https://medium.com/coinmonks/ethereum-token-standards-part-ii-erc721-4a4a7cbd5c74) +* [What Is ERC-1155 and How Does It Work?](https://academy.binance.com/en/articles/what-is-erc-1155-and-how-does-it-work) [[RU](https://academy.binance.com/ru/articles/what-is-erc-1155-and-how-does-it-work)] * [Что такое апрувы токенов (Token Approvals)?](https://revoke.cash/ru/learn/approvals/what-are-token-approvals) +* [Understanding ERC-20 Permit and Associated Risks](https://readmedium.com/understanding-erc-20-permit-and-associated-risks-41c29c969862) +* [ERC-2612: Permit Extension for EIP-20 Signed Approvals](https://eips.ethereum.org/EIPS/eip-2612) * Что такое decimals? Ответ от chat-gpt [тут](./img/Screenshot_1.png) и [тут](./img/Screenshot_2.png). И косвенный ответ [тут](https://ethereum.stackexchange.com/questions/134958/erc20-decimals-in-smart-contract). * [Base mechanics: minting, burning, staking](https://github.com/fullstack-development/web3-roadmap/blob/main/defi/tokens/tokenomics/token_mechanics.md) * [Стейблкоины. Как привязывают и почему не отвязывается!?](https://habr.com/ru/companies/metalamp/articles/763538/) From 00c134f4c2a2a920c41dab89a637407e280fc9e8 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Fri, 13 Sep 2024 12:57:54 +0400 Subject: [PATCH 13/93] add link to nft smart contract --- frontend-web3/practice/2-mint-nft.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/frontend-web3/practice/2-mint-nft.md b/frontend-web3/practice/2-mint-nft.md index cd6232b6..651d9bef 100644 --- a/frontend-web3/practice/2-mint-nft.md +++ b/frontend-web3/practice/2-mint-nft.md @@ -2,8 +2,6 @@ Минтинг NFT коллекции -**TODO: Добавить ссылку на контракт и гайд, как его задеплоить.** - ## Какие навыки даст задание? - Базовые навыки по работе с кошельками. Подключение/отключение кошелька, подпись сообщений. @@ -38,9 +36,7 @@ ## Смарт-контракт -**TODO: Добавить ссылку на контракт и гайд, как его задеплоить.** - -Для реализации функционала, описанного выше, был разработан смарт-контракт. На реальном проекте вам необходимо будет общаться с разработчиком смарт контракта, что бы он вам рассказал как и что работает. Но в данном задании, для вашего удобства, ниже представлено описание некоторых методов этого смарт контракта на чтение и запись. +Для реализации функционала, описанного выше, был разработан смарт-контракт. Смарт-контракт находится [здесь](https://github.com/fullstack-development/frontend-practice-nft), там же присутствует гайд по деплою (читать README). На реальном проекте вам необходимо будет общаться с разработчиком смарт контракта, что бы он вам рассказал как и что работает. Но в данном задании, для вашего удобства, ниже представлено описание некоторых методов этого смарт контракта на чтение и запись. ### Работа с ролями @@ -108,7 +104,7 @@ const merkleTree = new MerkleTree( ```json { - "airdrop": [ + "airdrop": [ // для этапа airdrop { "address": "0x0000000000000000000000000000000000000000", "proof": [ @@ -124,7 +120,7 @@ const merkleTree = new MerkleTree( ] } ], - "private": [...] + "private": [...] // для этапа private presale } ``` From 38c5d871e727faaa41993a0183944a10aa62da7d Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Mon, 16 Sep 2024 13:58:49 +0400 Subject: [PATCH 14/93] improve questions about etherscan in web3-frontend --- frontend-web3/basics.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md index 1abf4862..2077d7bf 100644 --- a/frontend-web3/basics.md +++ b/frontend-web3/basics.md @@ -90,7 +90,10 @@ ### Фронтенд * Как прочесть информацию из блокчейна и при чём тут RPC? * Почему при работе с числами из блокчейна нельзя пользоваться обычным типом `number`? Какой тип использовать вместо `number`? -* Что такое etherscan? +* Что такое etherscan? Есть ли аналоги в других сетях? + * Как посмотреть код контракта? + * Как посмотреть историю транзакций для выбранного контракта? + * Как посмотреть методы на чтение/запись контракта? Можно ли их вызвать? * Что такое TransactionReceipt? * Что такое viem? Что такое ethers.js? * Что такое wagmi? From 3903c38d820651d2e84a412f549df54fececab6b Mon Sep 17 00:00:00 2001 From: Everrest1 Date: Mon, 16 Sep 2024 20:35:12 +0300 Subject: [PATCH 15/93] Minor fix --- frontend/junior-3/seo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/seo.md b/frontend/junior-3/seo.md index eabc7685..ad0d7668 100644 --- a/frontend/junior-3/seo.md +++ b/frontend/junior-3/seo.md @@ -27,7 +27,7 @@ ### Ресурсы -* [Большая подборка материалов](https://habr.com/ru/articles/469139/) +* [Большая подборка материалов](https://habr.com/ru/articles/469139/), наиболее полезные: * [Как работает поиск Яндекса](https://yandex.ru/support/webmaster/yandex-indexing/site-indexing.html) * [Подробное руководство по принципам работы Google Поиска](https://developers.google.com/search/docs/fundamentals/how-search-works?hl=ru&visit_id=638608767731277346-2134489696&rd=1) * [Что такое структура сайта, как её создать и проанализировать](https://netpeaksoftware.com/ru/blog/site-structure-how-to-build-and-analyze-it) From 44cfa4e3189d3337969691658cf1bb6fc372ac7e Mon Sep 17 00:00:00 2001 From: Everrest1 Date: Tue, 17 Sep 2024 11:12:23 +0300 Subject: [PATCH 16/93] Correct site structure question --- frontend/junior-3/seo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/seo.md b/frontend/junior-3/seo.md index ad0d7668..433ef95a 100644 --- a/frontend/junior-3/seo.md +++ b/frontend/junior-3/seo.md @@ -10,7 +10,7 @@ * Коммерческие факторы * Поведенческие факторы * Юзабилити - * Как должна выглядеть идеальная seo-friendly структура сайта? + * Что такое структура сайта с точки зрения SEO? Как должна выглядеть идеальная SEO-friendly структура сайта? * Что такое нулевая позиция в выдаче? ### Оптимизация на фронтенде: From 32eef271a5768051adbcf9d7df63b2048d840310 Mon Sep 17 00:00:00 2001 From: Everrest1 Date: Tue, 17 Sep 2024 11:21:48 +0300 Subject: [PATCH 17/93] Uppercase SEO --- frontend/junior-3/seo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/seo.md b/frontend/junior-3/seo.md index 433ef95a..1c6c11eb 100644 --- a/frontend/junior-3/seo.md +++ b/frontend/junior-3/seo.md @@ -1,7 +1,7 @@ # Основы SEO ### Общие определения: - * Что такое seo? + * Что такое SEO? * Что такое ранжирование? * Что такое индексирование? * Как работают поисковые роботы? Чем отличается поиск Яндекс и Google? From 408c434f871cd28f9983ae8904f5f041b7fafb88 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Thu, 19 Sep 2024 11:30:26 +0400 Subject: [PATCH 18/93] imrpove questions about erc-20 and erc-721 in web3-frontend --- frontend-web3/basics.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md index 2077d7bf..df009d23 100644 --- a/frontend-web3/basics.md +++ b/frontend-web3/basics.md @@ -53,6 +53,8 @@ ### Токены * Что такое ERC-20 и ERC-721? В чем отличие этих токенов от нативной валюты блокчейна? + * Какие вы знаете методы у ERC-20 и ERC-721? + * Какие вы знаете популярные ERC-20 токены? * Что такое ERC-1155? * Что такое аппрув токена, зачем он нужен? * Как можно узнать количество токенов, разрешенных для управления сторонним адресом? @@ -68,6 +70,8 @@ ##### Ресурсы * [An Introduction to ERC-20 Tokens](https://academy.binance.com/en/articles/an-introduction-to-erc-20-tokens) +* [ERC-20: Token Standard](https://eips.ethereum.org/EIPS/eip-20) +* [ERC-721 Non-Fungible Token Standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-721/) * [Ethereum Token Standards Part-II (ERC721)](https://medium.com/coinmonks/ethereum-token-standards-part-ii-erc721-4a4a7cbd5c74) * [What Is ERC-1155 and How Does It Work?](https://academy.binance.com/en/articles/what-is-erc-1155-and-how-does-it-work) [[RU](https://academy.binance.com/ru/articles/what-is-erc-1155-and-how-does-it-work)] * [Что такое апрувы токенов (Token Approvals)?](https://revoke.cash/ru/learn/approvals/what-are-token-approvals) From cc6d9eb14de228856671c6530afb32b5ca02e390 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Wed, 25 Sep 2024 12:58:18 +0400 Subject: [PATCH 19/93] improve questions about etherscan --- frontend-web3/basics.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend-web3/basics.md b/frontend-web3/basics.md index df009d23..0370f928 100644 --- a/frontend-web3/basics.md +++ b/frontend-web3/basics.md @@ -24,7 +24,7 @@ * [What is Ethereum Gas? (Examples + Easy Explanation)](https://www.youtube.com/watch?v=3ehaSqwUZ0s) ### Смарт-контракты -* Что такое смарт-контракт и ABI? +* Что такое смарт-контракт? * Что такое “события” в смарт контракте? * Что такое indexed параметры? * В чем отличия функций view, pure, payable в смарт-контракте? @@ -97,7 +97,8 @@ * Что такое etherscan? Есть ли аналоги в других сетях? * Как посмотреть код контракта? * Как посмотреть историю транзакций для выбранного контракта? - * Как посмотреть методы на чтение/запись контракта? Можно ли их вызвать? + * Как посмотреть методы на чтение/запись контракта? Можно ли их вызвать через интерфейс etherscan? + * Что такое ABI контракта и где его взять? * Что такое TransactionReceipt? * Что такое viem? Что такое ethers.js? * Что такое wagmi? From f1aaf4e613177ae8902cec08ad912f1e444e49a8 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Wed, 25 Sep 2024 13:25:40 +0400 Subject: [PATCH 20/93] add linkts to figma files in practice tasks --- frontend-web3/practice/1-send-erc-20.md | 6 ++++++ frontend-web3/practice/2-mint-nft.md | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/frontend-web3/practice/1-send-erc-20.md b/frontend-web3/practice/1-send-erc-20.md index f9d26726..5da6d563 100644 --- a/frontend-web3/practice/1-send-erc-20.md +++ b/frontend-web3/practice/1-send-erc-20.md @@ -25,6 +25,12 @@ - Для работы с блокчейном рекомендуется использоваться [wagmi](https://wagmi.sh/) + [viem](https://viem.sh/). Для интерфейса подключения кошелька можно использовать одно из [сторонних решений](https://wagmi.sh/react/guides/connect-wallet#third-party-libraries). - Для запросов в блокчейн использовать в качестве RPC провайдера [стороннего провайдера](https://wagmi.sh/core/api/transports/http), а не публичные RPC URL. Например, Alchemy, RPC URL которого можно получить в [личном кабинете](https://dashboard.alchemy.com/). +## Макеты + +Макеты можно взять [тут](https://www.figma.com/design/5bea2k2sfc8CMytdahfeKW/MetaLamp-Developers-Roadmap-%2F-Frontend-Web3?node-id=0-1&node-type=canvas&t=1DOUk1Gc2KxNbpNr-0). Ссылка на конкретные макеты больше нужна для понимания того, как может выглядеть ваш интерфейс. Вы можете использовать эти макеты или реализовать свой интерфейс. + +В макетах есть Preview Mode, можете прокликать интерфейс. + ## Смарт контракт Отдельного смарт контракта для реализации данного функционала не требуется. Стандарт ERC-20 подразумевает наличие некоторого поведения и методов по умолчанию, которых нам достаточно. В частности такие методы как `transfer`, `approve`, `balanceOf` и другие, есть у любого ERC-20 токена. Вы можете импортировать стандартное ABI для всех ERC-20 токенов из viem - `import { erc20Abi } from 'viem';`. \ No newline at end of file diff --git a/frontend-web3/practice/2-mint-nft.md b/frontend-web3/practice/2-mint-nft.md index 651d9bef..d5f76812 100644 --- a/frontend-web3/practice/2-mint-nft.md +++ b/frontend-web3/practice/2-mint-nft.md @@ -33,6 +33,12 @@ - Для работы с блокчейном рекомендуется использоваться [wagmi](https://wagmi.sh/) + [viem](https://viem.sh/). Для интерфейса подключения кошелька можно использовать одно из [сторонних решений](https://wagmi.sh/react/guides/connect-wallet#third-party-libraries). - Для запросов в блокчейн использовать в качестве RPC провайдера [стороннего провайдера](https://wagmi.sh/core/api/transports/http), а не публичные RPC URL. Например, Alchemy, RPC URL которого можно получить в [личном кабинете](https://dashboard.alchemy.com/). +## Макеты + +Макеты можно взять [тут](https://www.figma.com/design/5bea2k2sfc8CMytdahfeKW/MetaLamp-Developers-Roadmap-%2F-Frontend-Web3?node-id=2008-1789&node-type=canvas&t=HaYr0qVXTtVr2aDV-0). Ссылка на конкретные макеты больше нужна для понимания того, как может выглядеть ваш интерфейс. Вы можете использовать эти макеты или реализовать свой интерфейс. Обратите внимание, что в макетах нет интерфейса админки, вам его нужно продумать самим. + +В макетах есть Preview Mode, можете прокликать интерфейс. + ## Смарт-контракт From f403058f3e2a818d4044a49640077527f96a9547 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 10 Oct 2024 12:15:19 +0300 Subject: [PATCH 21/93] add react v18 topics --- frontend/junior-1/react.md | 41 ++++++------ frontend/junior-2/react.md | 20 ++++-- frontend/junior-3/data.md | 4 ++ frontend/junior-3/react.md | 128 ++++++++++++++++++++++++++++++++++++- 4 files changed, 169 insertions(+), 24 deletions(-) diff --git a/frontend/junior-1/react.md b/frontend/junior-1/react.md index 201ccc09..1bc47cb4 100644 --- a/frontend/junior-1/react.md +++ b/frontend/junior-1/react.md @@ -17,43 +17,46 @@ ``` * Что такое Virtual DOM и зачем он нужен? +* Что такое React Fragment? Для чего он нужен? Как его использовать? * Что такое `props` у компонента? +* `props.children` + * Что это такое? + * Когда может быть полезным? + * Что позволяет делать `React.Children` API? * Что такое условный рендеринг? * В чём проблема следующего кода `

{items.length && }

`? -* Что такое хуки? - * Какие существуют правила при работе с хуками? +* Что такое чистые компоненты и почему компоненты должны быть чистыми (не путать с `React.PureComponents`)? + * Где можно вызывать побочные эффекты? * Что такое `stateful` и `stateless` компоненты? - * Что делает хук `useState`? Как обновить состояние? - * Как обновить состояние из `useState` на основе предыдущего значения? Какие могут при этом возникнуть проблемы? + * Что делает хук `useState`? Как обновить состояние? + * Произойдет ли ререндер компонента, если сеттер установил значение, совпадающее с предыдущим? + * Как обновить состояние из `useState` на основе предыдущего значения? Какие могут при этом возникнуть проблемы? * Что такое top-down data flow? Что является основным механизмом синхронизации нескольких компонент? + * Что такое декларативное UI программирование? Чем оно отличается от императивного подхода? +* Controlled и uncontrolled компоненты + * Что это такое? Как происходит работа с инпутами? + * Как задать дефолтное значение для инпута в uncontrolled компоненте? +* Что такое хуки? + * Какие существуют правила при работе с хуками? * Lifecycle of reactive effects * Что это такое? * Что такое эффекты? Что означает "синхронизация с эффектом"? * Для чего предназначен хук `useEffect`? Как с ним работать? + * Для чего не должен использоваться `useEffect`? Почему? * Что может возвращать колбэк, передаваемый в `useEffect`? * Что такое массив зависимостей? Рассказать как он влияет на работу хука на примере useEffect (в том числе на возвращаемое колбэком значение). * У вас есть несколько эффектов. Куда вы их поместите, в один общий `useEffect` или в разные? Почему? -* `props.children` - * Что это такое? - * Когда может быть полезным? - * Что позволяет делать `React.Children` API? -* Что такое чистые компоненты и почему компоненты должны быть чистыми (не путать с `React.PureComponents`)? - * Где можно вызывать побочные эффекты? -* Что такое React Fragment? Для чего он нужен? Как его использовать? * refs * Что это такое? Зачем нужны? Как их использовать? - * Как и для чего использовать хук `useRef`? + * Как и для чего использовать хуки `useRef` и `useImperativeHandle`? * Что делает и зачем нужен метод `React.forwardRef`? + * Как управлять массивом ref-ов? * Почему refs стоит использовать умеренно? -* Controlled и uncontrolled компоненты - * Что это такое? Как происходит работа с инпутами? - * Как задать дефолтное значение для инпута в uncontrolled компоненте? ### Ресурсы -* [React Documentation](https://reactJS.org/docs/getting-started.html) -* [New React Documentation](https://beta.reactjs.org/) +* [React Documentation](https://react.dev/learn) * [Making Sense of React Hooks](https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889) * [React hooks: not magic, just arrays](https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e) -* [Keeping Components Pure](https://beta.reactjs.org/learn/keeping-components-pure) -* [Lifecycle of reactive effects](https://beta.reactjs.org/learn/lifecycle-of-reactive-effects) +* [Keeping Components Pure](https://react.dev//learn/keeping-components-pure) +* [Lifecycle of reactive effects](https://react.dev//learn/lifecycle-of-reactive-effects) diff --git a/frontend/junior-2/react.md b/frontend/junior-2/react.md index bfd6c038..be9b2e3e 100644 --- a/frontend/junior-2/react.md +++ b/frontend/junior-2/react.md @@ -1,7 +1,7 @@ # React * useEffect - * Нужно ли указывать функции в виде зависимостей эффектов? + * Нужно ли указывать функции в виде зависимостей эффектов? Как минимизировать количество зависимостей? * Что выведется в консоли для следующего кода, если быстро нажать 5 раз на кнопку, и почему? ```javascript function Counter() { @@ -46,6 +46,9 @@ ); } ``` + * В какой момент может выполниться эффект и функция очистки? + * Для чего предназначены хуки `useLayoutEffect`, `useInsertionEffect`, `useSyncExternalStore`? + * Почему использовать `fetch` в `useEffect` - не самая хорошая идея? Какие есть альтернативы? * Performance * Для чего в хук `useState` можно передавать функцию вместо `initialState`? * Когда передача инлайн-коллбека ухудшает производительность и почему? Пример: ` handleClick(e, user)}>` @@ -78,8 +81,9 @@ ); }; - ``` + ``` * State Management + * Каков алгоритм организации состояния в react при декларативном программировании? * Какие есть способы организации состояния, когда в этом состоянии нуждаются несколько компонентов? * Почему поднятие состояния до общего родителя может быть неудобным? * Для чего предназначен хук `useReducer`? Как с ним работать? @@ -89,6 +93,7 @@ * Как обновить Context из глубоко вложенной компоненты (т.е. пробрасывать коллбэк в таком случае - очень неудобное решение)? * Можно ли вкладывать провайдеры одного и того же Context друг в друга? Из какого провайдера при этом будут браться данные? * Почему не стоит злоупотреблять Context? + * Какие группы пакетов по управлению состоянием существуют и какие проблемы каждая решает? Какие особенности реализации используются и какие ограничения из-за этого могут накладываться? * Что такое HOC? Когда хоки могут быть полезны? * Portals * Что это такое? Зачем нужны? Как использовать? @@ -104,11 +109,18 @@ } } ``` +* Как отрендерить разный контент между клиентом и сервере и не нарушить процесс гидратации? ### Ресурсы -* [React Documentation](https://reactJS.org/docs/getting-started.html) +* [React Documentation](https://react.dev/learn) * [Полное руководство по useEffect](https://habr.com/ru/company/ruvds/blog/445276/) - объёмная, но очень классная статья по useEffect, которая поможет раскрыть глаза на многие вещи. Возможно придётся осилить в 2 подхода. * [Все ли вы знаете о useCallback](https://habr.com/ru/post/529950/) * [Интересная ветка обсуждения в комментариях статьи выше](https://habr.com/ru/post/529950/comments/#comment_22380330) -* [Passing Data Deeply with Context](https://beta.reactjs.org/learn/passing-data-deeply-with-context) +* [Passing Data Deeply with Context](https://react.dev//learn/passing-data-deeply-with-context) +* [STATE MANAGEMENT - лучший стейт менеджер для react?](https://www.youtube.com/watch?v=AUbWwzez_Dg) +* [zustand comparison](https://zustand.docs.pmnd.rs/getting-started/comparison) +* [recoiljs motivation](https://recoiljs.org/docs/introduction/motivation/) +* [jotai comparison](https://jotai.org/docs/basics/comparison) +* [jotai concepts](https://jotai.org/docs/basics/concepts) +* [mobX principles](https://mobx.js.org/the-gist-of-mobx.html#principles) \ No newline at end of file diff --git a/frontend/junior-3/data.md b/frontend/junior-3/data.md index ebc03128..3cc8bb96 100644 --- a/frontend/junior-3/data.md +++ b/frontend/junior-3/data.md @@ -13,11 +13,15 @@ f() f({}) ``` +* Какие способы обновить глубоко вложенное значение есть? Что можно сделать, чтобы не было необходимости работать с глубоко вложенными значениями? * Утечки памяти - что это? Когда они могут возникать? Как их находить и устранять? * Какие есть способы хранения информации на клиенте? В каких случаях какой способ лучше использовать? Какие у каждого способа есть особенности? ### Ресурсы +* [Как обновить вложенные объекты](https://react.dev/learn/updating-objects-in-state) +* [Как обновить вложенные массивы](https://react.dev/learn/updating-arrays-in-state) +* [Решения для обновления вложенных значений](https://zustand.docs.pmnd.rs/guides/updating-state#with-optics-ts) * [4 вида утечек памяти в JavaScript и как с ними бороться](https://habr.com/post/309318) * [Как находить и устранять утечки памяти на примере Яндекс.Почты](https://habr.com/company/yandex/blog/195198/) * [Обзор средств хранения данных на клиентской стороне](http://prgssr.ru/development/obzor-sredstv-hraneniya-dannyh-na-klientskoj-storone.html) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index a249ec38..c90c5466 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -3,6 +3,107 @@ * Reconciliation * Что такое? Какую функцию выполняет? * Каким образом reconciliation алгоритм использует тип элемента (что происходит, если тип изменился, не изменился и т.д.)? + * Являются ли следующие два примера эквивалентными? Почему? + + ```jsx + if (isPacked) { + return
  • {name} ✅
  • ; + } + return
  • {name}
  • ; + ``` + + ```jsx + return ( +
  • + {isPacked ? name + ' ✅' : name} +
  • + ); + ``` + + * Произойдет ли сброс состояния `Counter`? Почему? + + ```jsx + export default function App() { + const [isFancy, setIsFancy] = useState(false); + if (isFancy) { + return ( +
    + + +
    + ); + } + return ( +
    + + +
    + ); + } + ``` + + * Произойдет ли сброс состояния `Counter`? Почему? + + ```jsx + {isFancy ? ( +
    + +
    + ) : ( +
    + +
    + )} + ``` + + * В чем проблемное место и как надо поступить? + + ```jsx + export default function MyComponent() { + const [counter, setCounter] = useState(0); + + function MyTextField() { + const [text, setText] = useState(''); + + return ( + setText(e.target.value)} + /> + ); + } + } + ``` + + ```jsx + return ( + <> + + + + ); + ``` + * Атрибут `key` * Зачем нужен? * Почему лучше не использовать индекс элемента массива в качестве значения? Когда этим правилом можно пренебречь? @@ -14,6 +115,29 @@ ``` Предположим, что в каждом инпуте содержится какой-то текст. Если добавить в начало `list` еще один элемент, то какой из инпутов окажется пустым и почему? + * Как сбросить внутренние состояния компонента? + * как сохранить внутренние состояния при размонтировании? +* Concurrent mode + * Что это такое? Какие проблемы решает? Чем отличается от режима по-умолчанию? + * Как перейти в данный режим? + * Какие в react есть категории update? Как они работают? + * Для чего предназначены и как использовать хуки: `useTransition` и `useDeferredValue`? + * В какой последовательности сработает `console.log`, почему? + + ```js + console.log(1); + startTransition(() => { + console.log(2); + setPage('/about'); + }); + console.log(3); + ``` + +* Batching + * Что это такое? + * В каких случаях происходит? Что для этого нужно? + * Когда следует задумываться о необходимости такой оптимизации? + * Как вызвать немедленное обновление состояний компонента внутри `callback`? Когда это может быть полезно? * Performance * Что такое windowing или virtualizing списков? * Всегда ли происходит перерисовка DOM-элемента, если `shouldComponentUpdate` вернул `true`? @@ -73,9 +197,11 @@ ### Ресурсы -* [React Documentation](https://reactjs.org/docs/getting-started.html) +* [React Documentation](https://react.dev/learn) * [React as a UI Runtime](https://overreacted.io/react-as-a-ui-runtime/) * [Index as a key is an anti-pattern](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318) * [React Fiber Architecture](https://github.com/acdlite/react-fiber-architecture) - здесь неплохо написано про reconciliation в целом, часть про детали реализации (fiber) опциональна. +* [React concurrency](https://www.youtube.com/watch?v=M1OBMTYsKpo) +* [Батчинг в react](https://www.youtube.com/watch?v=VfQ-qSjIalU) * [React events in depth w/ Kent C. Dodds, Ben Alpert, & Dan Abramov](https://www.youtube.com/watch?v=dRo_egw7tBc) * [Getting to know React DOM’s event handling system inside out](https://medium.com/the-guild/getting-to-know-react-doms-event-handling-system-inside-out-378c44d2a5d0) From 5b5255b6cd2be2c7a40d4f6f14cf5bfe8cc5be67 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 7 Nov 2024 20:34:14 +0300 Subject: [PATCH 22/93] fix(frontend/junior-3/react): some wording improvement --- frontend/junior-3/react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index c90c5466..c159702e 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -116,7 +116,7 @@ ``` Предположим, что в каждом инпуте содержится какой-то текст. Если добавить в начало `list` еще один элемент, то какой из инпутов окажется пустым и почему? * Как сбросить внутренние состояния компонента? - * как сохранить внутренние состояния при размонтировании? + * Как сохранить внутренние состояния для последующего использования при необходимости скрыть результат рендера? * Concurrent mode * Что это такое? Какие проблемы решает? Чем отличается от режима по-умолчанию? * Как перейти в данный режим? From 93ec7427d2ffec03760612a9925d7bd12a0fd137 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 7 Nov 2024 21:01:29 +0300 Subject: [PATCH 23/93] feat(frontend/junior-3/react): + reconciliation example question --- frontend/junior-3/react.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index c159702e..fad9c5f2 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -104,6 +104,15 @@ ); ``` + * Будет ли пересоздаваться компонент ``, если я добавлю/удалю что-то в массиве `data`? + + ```jsx + + {data.map((i) => )} + + + ``` + * Атрибут `key` * Зачем нужен? * Почему лучше не использовать индекс элемента массива в качестве значения? Когда этим правилом можно пренебречь? From 8f6dcae55bb4ebc6d302e9bfe684dc9cbbdda3e2 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 7 Nov 2024 21:10:50 +0300 Subject: [PATCH 24/93] fix(frontend/junior-3/react): some wording improvement --- frontend/junior-3/react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index fad9c5f2..e8ce6bdf 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -104,7 +104,7 @@ ); ``` - * Будет ли пересоздаваться компонент ``, если я добавлю/удалю что-то в массиве `data`? + * Будет ли заново монтироваться компонент ``, если я добавлю/удалю что-то в массиве `data`? ```jsx From 01fc012f914d8f01f2058b819a94917f2e513012 Mon Sep 17 00:00:00 2001 From: Olga Klimenko Date: Mon, 11 Nov 2024 17:05:34 +0700 Subject: [PATCH 25/93] add nodejs jun-1 --- backend/README.md | 1 + backend/node.js/README.md | 8 +++++ backend/node.js/junior-1/README.md | 8 +++++ backend/node.js/junior-1/databases/MongoDB.md | 25 ++++++++++++++ backend/node.js/junior-1/databases/NoSQL.md | 9 +++++ backend/node.js/junior-1/databases/ORM.md | 22 ++++++++++++ .../node.js/junior-1/databases/PostgreSQL.md | 28 +++++++++++++++ backend/node.js/junior-1/databases/README.md | 7 ++++ backend/node.js/junior-1/nestjs.md | 30 ++++++++++++++++ backend/node.js/junior-1/nodejs.md | 34 +++++++++++++++++++ backend/shared/junior-1/db.md | 3 ++ 11 files changed, 175 insertions(+) create mode 100644 backend/node.js/README.md create mode 100644 backend/node.js/junior-1/README.md create mode 100644 backend/node.js/junior-1/databases/MongoDB.md create mode 100644 backend/node.js/junior-1/databases/NoSQL.md create mode 100644 backend/node.js/junior-1/databases/ORM.md create mode 100644 backend/node.js/junior-1/databases/PostgreSQL.md create mode 100644 backend/node.js/junior-1/databases/README.md create mode 100644 backend/node.js/junior-1/nestjs.md create mode 100644 backend/node.js/junior-1/nodejs.md diff --git a/backend/README.md b/backend/README.md index 431fa8c1..9eefe29c 100644 --- a/backend/README.md +++ b/backend/README.md @@ -1,6 +1,7 @@ # Programming languages - [Haskell](./haskell/README.md) +- [Node.js](./node.js/README.md) - [Python](./python/README.md) ## Optional topics diff --git a/backend/node.js/README.md b/backend/node.js/README.md new file mode 100644 index 00000000..8015e78e --- /dev/null +++ b/backend/node.js/README.md @@ -0,0 +1,8 @@ +# Список уровней: + +- **Junior:** + * [junior-1](./junior-1/README.md) + +- **Middle** + +- **Senior** diff --git a/backend/node.js/junior-1/README.md b/backend/node.js/junior-1/README.md new file mode 100644 index 00000000..4ee04a24 --- /dev/null +++ b/backend/node.js/junior-1/README.md @@ -0,0 +1,8 @@ +# Node.js Junior 1 level + +- [JavaScript](../../../frontend/junior-1/js.md) +- [Node.js](../junior-1/nodejs.md) +- [Nest.js](../junior-1/nestjs.md) +- [DB](../junior-1/db.md) +- [Testing](../../shared/junior-1/testing.md) +- [Git](../../shared/junior-1/git.md) diff --git a/backend/node.js/junior-1/databases/MongoDB.md b/backend/node.js/junior-1/databases/MongoDB.md new file mode 100644 index 00000000..21b0a8e8 --- /dev/null +++ b/backend/node.js/junior-1/databases/MongoDB.md @@ -0,0 +1,25 @@ +# MongoDB + + +* What is MongoDB? +* What are the basic most commonly used types? +* What are these methods for? + * insertOne, insertMany + * find + * updateOne, updateMany, replaceOne, replaceMany + * deleteOne, deleteMany, drop +* What are these operators for? + * $eq, $gt, $lt, $lte, $gte, $ne + * $include, $exclude + * $in, $nin, $all + * $and, $or, $not, $nor + * $match, $group, $sort, $skip, $limit +* What are replications? How replications relate to transactions? +* How to create dump? +* How to restore dump? + +### Resources + +* [MongoDB CRUD Operations](https://www.mongodb.com/resources/products/fundamentals/crud) +* [MongoDB Operators](https://www.mongodb.com/docs/manual/reference/operator/) +* [MongoDB Transactions](https://www.mongodb.com/docs/manual/core/transactions/) diff --git a/backend/node.js/junior-1/databases/NoSQL.md b/backend/node.js/junior-1/databases/NoSQL.md new file mode 100644 index 00000000..ea83f207 --- /dev/null +++ b/backend/node.js/junior-1/databases/NoSQL.md @@ -0,0 +1,9 @@ +# NoSQL + +* What is NoSQL database? +* What the difference from a relational db? +* NoSQL use cases. When it should be used? + +### Resources + +* [What is NoSQL?](https://www.mongodb.com/resources/basics/databases/nosql-explained) diff --git a/backend/node.js/junior-1/databases/ORM.md b/backend/node.js/junior-1/databases/ORM.md new file mode 100644 index 00000000..67d0333f --- /dev/null +++ b/backend/node.js/junior-1/databases/ORM.md @@ -0,0 +1,22 @@ +# ORM + +## Common + +* What is ORM? Why do we prefer to use ORMs instead of native drivers? + +## Typeorm +* What it is. +* Write a simple table with numbers, strings, and arrays. +* Write the relationship options: + * OneToOne. + * ManyToOne (OneToMany). + * ManyToMany. +* Migrations + * What are the commands for running and creating migrations? + * If you need to add a new field to an existing table on a prod (or change the field type) what do you do? +* What is QueryBuilder? +* How do you load a record including relationships from a database? How to load only certain fields? Sorting and pagination? + +### Resources + +* [Type ORM documentation](https://typeorm.io/) diff --git a/backend/node.js/junior-1/databases/PostgreSQL.md b/backend/node.js/junior-1/databases/PostgreSQL.md new file mode 100644 index 00000000..a90c1415 --- /dev/null +++ b/backend/node.js/junior-1/databases/PostgreSQL.md @@ -0,0 +1,28 @@ +# PostgreSQL + +* What is PostreSQL? +* What are the basic most commonly used types? +* What are domains? How to create a domain? How to create custom type? Enum type? +* What is constraint? +* How to use this constraints? + * Primary Key + * Foreign Key + * Unique + * Not Null +* How to use transactions in sql? +* How to create dump? +* How to restore dump? +* What is a View table? + * How to create it? + * How to update it? + * What is materialized views? + + +### Resources + +* [Postgresql documentation: Chapter 8. Data Types](https://www.postgresql.org/docs/current/datatype.html) +* [A Look at PostgreSQL User-defined Data Types](https://neon.tech/postgresql/postgresql-tutorial/postgresql-user-defined-data-types) +* [PostgreSQL enum](https://neon.tech/postgresql/postgresql-tutorial/postgresql-enum) +* [Postgres Constraints for Newbies](https://www.crunchydata.com/blog/postgres-constraints-for-newbies) +* [PostgreSQL Transaction](https://neon.tech/postgresql/postgresql-tutorial/postgresql-transaction) +* [PostgreSQL Views](https://neon.tech/postgresql/postgresql-views) diff --git a/backend/node.js/junior-1/databases/README.md b/backend/node.js/junior-1/databases/README.md new file mode 100644 index 00000000..ba86f18c --- /dev/null +++ b/backend/node.js/junior-1/databases/README.md @@ -0,0 +1,7 @@ +# Databases + +* [Relational database and SQL](../../../shared/junior-1/db.md) +* [NoSQL](./NoSQL.md) +* [PostgreSQL](./PostgreSQL.md) +* [MongoDB](./MongoDB.md) +* [ORM](./ORM.md) diff --git a/backend/node.js/junior-1/nestjs.md b/backend/node.js/junior-1/nestjs.md new file mode 100644 index 00000000..f1be9d58 --- /dev/null +++ b/backend/node.js/junior-1/nestjs.md @@ -0,0 +1,30 @@ +# Nest.js + + +* What is it and what is it used for? +* What are Dependency injection and Inversion of Control? How does it relate to NestJS? +* Tell about Module, Provider, Controller. + * What is Scope? How do different values change the behavior of the application? +* Controller + * Http decorators + * Request validation +* What is Guard and Strategy? How to use it to create auth module? +* What are the basic ways to catch exceptions? +* How to resolve cyclic dependencies issue? +* What is Middleware? What is it used for? How to create it? +* What is Interceptor? +* How to create custom decorators? +* Tell about life cycles and there purpose? +* What is Dynamic module? How to create it? + * What is the difference between forRoot, forFeature and register? +* How to do unit testing of a module? +* What is Custom providers? How to use it in testing? +* How to setup CORS? +* How to rate-limit an app? +* How to create a microservice and connect it to another NestJS application? + * How to make a two-way system so that both applications are both consumers and producers at the same time? + + +### Resources + +* [NestJS documentation](https://docs.nestjs.com/) diff --git a/backend/node.js/junior-1/nodejs.md b/backend/node.js/junior-1/nodejs.md new file mode 100644 index 00000000..0afb5d7a --- /dev/null +++ b/backend/node.js/junior-1/nodejs.md @@ -0,0 +1,34 @@ +# Node.js + +* What is NodeJS? +* What parts does node consist of? +* What is the difference between node and js in the browser? +* What is the difference between CommonJS and ES modules in node? +* What is an EventEmitter? What can it be used for? +* What is an Event Loop? How does it work? How is it different from event loop in browser? +* How to use a debugger? +* What modules are there for working with the file system? +* What is the child_process module for? + * What is the difference between spawn and exec? + * How to create a process so that it can send logs in the current application console in runtime? + * How to transfer a running process to promises? +* What is a WorkerThread and how to work with it? +* What is a garbage collector and how does it work? Under what conditions can a garbage collector fail? +* What are Stream? What types of streams are there? What can they be used for? + +### Resources + +* [Introduction to Node.js](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs) +* [Node.js Under The Hood Series' Articles](https://dev.to/_staticvoid/series/2008) +* [Differences between Node.js and the Browser](https://nodejs.org/en/learn/getting-started/differences-between-nodejs-and-the-browser/#differences-between-nodejs-and-the-browser) +* [Understanding CommonJS vs. ES Modules in JavaScript](https://www.syncfusion.com/blogs/post/js-commonjs-vs-es-modules) +* [CommonJS vs. ES modules in Node.js](https://blog.logrocket.com/commonjs-vs-es-modules-node-js/) +* [The Node.js Event Loop](https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick#what-is-the-event-loop) +* [Don't Block the Event Loop (or the Worker Pool)](https://nodejs.org/en/learn/asynchronous-work/dont-block-the-event-loop) +* [JavaScript Visualized Series' Articles](https://dev.to/lydiahallie/series/3341) +* [The Node.js Event emitter](https://nodejs.org/en/learn/asynchronous-work/the-nodejs-event-emitter#the-nodejs-event-emitter) +* [Node.js v23.1.0 documentation: Debugger](https://nodejs.org/api/debugger.html) +* [Node.js v23.1.0 documentation: Child process](https://nodejs.org/api/child_process.html#child-process) +* [Node.js v23.1.0 documentation: Worker threads](https://nodejs.org/api/worker_threads.html#worker-threads) +* [Garbage collection](https://javascript.info/garbage-collection) +* [Node.js v23.1.0 documentation: Stream](https://nodejs.org/api/stream.html#stream) \ No newline at end of file diff --git a/backend/shared/junior-1/db.md b/backend/shared/junior-1/db.md index cc3e1980..f13e2cd8 100644 --- a/backend/shared/junior-1/db.md +++ b/backend/shared/junior-1/db.md @@ -17,6 +17,8 @@ - [What is a database?](https://www.oracle.com/database/what-is-database/) - [What is a relational database?](https://www.oracle.com/database/what-is-a-relational-database/) +- [Relational database](https://www.techtarget.com/searchdatamanagement/definition/relational-database) +- [Реляционные базы данных](https://yandex.cloud/ru/docs/glossary/relational-databases?utm_referrer=https%3A%2F%2Fgist.github.com%2F) ## SQL @@ -41,3 +43,4 @@ #### Resources - [SQL Tutorial](https://www.w3schools.com/sql/default.asp) +- [Введение в SQL и работу с базой данных](https://netology.ru/programs/vvedenie-v-sql-i-rabotu-s-bazoi-dannih#/) From b333916b3f18b55c5dac336342f62ec5b6b09679 Mon Sep 17 00:00:00 2001 From: ivtarasov Date: Mon, 11 Nov 2024 19:19:09 +0300 Subject: [PATCH 26/93] jun3/ts: improve formatting --- frontend/junior-3/ts.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/junior-3/ts.md b/frontend/junior-3/ts.md index e1cf8d21..b7b4253c 100644 --- a/frontend/junior-3/ts.md +++ b/frontend/junior-3/ts.md @@ -39,10 +39,11 @@ // Example: const personalInformation: IPersonalInformation = { - age: 25, - name: 'NameOfAvenger', - superpower: 'SuperpowerOfAvenger' + age: 25, + name: 'NameOfAvenger', + superpower: 'SuperpowerOfAvenger' }; + const survivedAvengers: SurvivedAvengers<'Thor' | 'Hawkeye' | 'Iron Man'> = { Thor: personalInformation, Hawkeye: personalInformation, From f87a96cb86e07ed3492840d8f4033048ac3aae50 Mon Sep 17 00:00:00 2001 From: ivtarasov Date: Wed, 13 Nov 2024 16:34:22 +0300 Subject: [PATCH 27/93] jun3/git: refactor filter paragraph --- shared/junior-3/git.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/junior-3/git.md b/shared/junior-3/git.md index a09dc95e..162a4437 100644 --- a/shared/junior-3/git.md +++ b/shared/junior-3/git.md @@ -13,7 +13,7 @@ * Как можно изменить историю коммитов? Где какой способ стоит применять? Рассказать в этом контексте про команды: * `commit` с флагом `--amend` * `cherry-pick` - * `filter-branch` + * `filter-branch/git-filter-repo` * `rebase` * Что такое интерактивный режим ребейза? Что он позволяет делать? * Какие есть опасности при использовании ребейза? From 2612c2fbc376d6f823ed94822e08459711f396fc Mon Sep 17 00:00:00 2001 From: ivtarasov Date: Wed, 13 Nov 2024 16:44:47 +0300 Subject: [PATCH 28/93] fix: fix formatting --- shared/junior-3/git.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/junior-3/git.md b/shared/junior-3/git.md index 162a4437..bbb03b06 100644 --- a/shared/junior-3/git.md +++ b/shared/junior-3/git.md @@ -13,7 +13,7 @@ * Как можно изменить историю коммитов? Где какой способ стоит применять? Рассказать в этом контексте про команды: * `commit` с флагом `--amend` * `cherry-pick` - * `filter-branch/git-filter-repo` + * `filter-branch`/`git-filter-repo` * `rebase` * Что такое интерактивный режим ребейза? Что он позволяет делать? * Какие есть опасности при использовании ребейза? From bca0e2fa326f64a187bccc7040a883b36a961b09 Mon Sep 17 00:00:00 2001 From: AndreiKochanov Date: Fri, 15 Nov 2024 17:51:24 +0300 Subject: [PATCH 29/93] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=202=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B8=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20Rest=20API.=20=20=20=20=20=D0=A2=D1=83=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B0=D0=BB=20-=20https://www.restapitutoria?= =?UTF-8?q?l.com/=20=20=20=20=20C=D1=82=D0=B0=D1=82=D1=8C=D1=8F=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=A5=D0=B0=D0=B1=D1=80=D0=B5=20-=20https://habr.com/?= =?UTF-8?q?ru/companies/oleg-bunin/articles/433322/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/junior-3/api.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/junior-3/api.md b/frontend/junior-3/api.md index d8e115f9..25075f0d 100644 --- a/frontend/junior-3/api.md +++ b/frontend/junior-3/api.md @@ -9,6 +9,8 @@ ### Ресурсы +* [REST API Tutorial](https://www.restapitutorial.com/) +* [JSON API – работаем по спецификации](https://habr.com/ru/companies/oleg-bunin/articles/433322/) * [Nate Barbettini – API Throwdown: RPC vs REST vs GraphQL, Iterate 2018](https://www.youtube.com/watch?v=IvsANO0qZEg) * [JSON API Specification](http://jsonapi.org/format/) * [JSON RPC Specification](https://www.jsonrpc.org/specification) From 3fe6073bbaf72a8373c117a9d453184410d138d5 Mon Sep 17 00:00:00 2001 From: andreikochanov Date: Fri, 15 Nov 2024 19:15:22 +0300 Subject: [PATCH 30/93] =?UTF-8?q?=D0=BF=D0=BE=D0=BC=D0=B5=D0=BD=D1=8F?= =?UTF-8?q?=D0=BB=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B8=20=D0=BC=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/junior-3/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/api.md b/frontend/junior-3/api.md index 25075f0d..a1f426e6 100644 --- a/frontend/junior-3/api.md +++ b/frontend/junior-3/api.md @@ -10,8 +10,8 @@ ### Ресурсы * [REST API Tutorial](https://www.restapitutorial.com/) -* [JSON API – работаем по спецификации](https://habr.com/ru/companies/oleg-bunin/articles/433322/) * [Nate Barbettini – API Throwdown: RPC vs REST vs GraphQL, Iterate 2018](https://www.youtube.com/watch?v=IvsANO0qZEg) +* [JSON API – работаем по спецификации](https://habr.com/ru/companies/oleg-bunin/articles/433322/) * [JSON API Specification](http://jsonapi.org/format/) * [JSON RPC Specification](https://www.jsonrpc.org/specification) * [GraphQL Specification](https://facebook.github.io/graphql/) From 446458e542181d2e8c5521caa152d61ae46844c6 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Tue, 19 Nov 2024 15:01:48 +0400 Subject: [PATCH 31/93] fix side effects article link --- frontend/middle-1/fp.md | 2 +- frontend/middle-1/oop.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/middle-1/fp.md b/frontend/middle-1/fp.md index 1677fe40..8ae05c27 100644 --- a/frontend/middle-1/fp.md +++ b/frontend/middle-1/fp.md @@ -72,5 +72,5 @@ * [Перевод](https://habr.com/en/post/337880/) * [What is idempotence?](https://szymonkrajewski.pl/what-is-idempotence/) * [Why Functional Programming? The Benefits of Referential Transparency](https://sookocheff.com/post/fp/why-functional-programming/) -* [Осторожно! Возможны побочные эффекты](https://blog.csssr.ru/2017/10/07/side-effects) +* [Осторожно! Возможны побочные эффекты](https://blog.csssr.com/ru/article/side-effects/) * [Thirteen ways of looking at a turtle](https://fsharpforfunandprofit.com/posts/13-ways-of-looking-at-a-turtle/) diff --git a/frontend/middle-1/oop.md b/frontend/middle-1/oop.md index 51dd317f..dfdd80b0 100644 --- a/frontend/middle-1/oop.md +++ b/frontend/middle-1/oop.md @@ -21,7 +21,7 @@ ### Ресурсы -* [Сайд эффекты](http://blog.csssr.ru/2017/10/07/side-effects) +* [Осторожно! Возможны побочные эффекты](https://blog.csssr.com/ru/article/side-effects/) * [Composition vs inheritance](https://javarevisited.blogspot.com/2013/06/why-favor-composition-over-inheritance-java-oops-design.html) * [Наследование vs Композиция vs Агрегация](http://sergeyteplyakov.blogspot.com/2012/12/vs-vs.html) * [Wikipedia: Наследование](https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D0%BA%D0%B0%D0%BF%D1%81%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)) From f17c459745926f6429226e9af7f1d4c8403c0fb4 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 28 Nov 2024 15:45:58 +0300 Subject: [PATCH 32/93] fix(frontend/junior-1/react): hooks rule before useState --- frontend/junior-1/react.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/junior-1/react.md b/frontend/junior-1/react.md index 1bc47cb4..057bc5df 100644 --- a/frontend/junior-1/react.md +++ b/frontend/junior-1/react.md @@ -27,6 +27,8 @@ * В чём проблема следующего кода `

    {items.length && }

    `? * Что такое чистые компоненты и почему компоненты должны быть чистыми (не путать с `React.PureComponents`)? * Где можно вызывать побочные эффекты? +* Что такое хуки? + * Какие существуют правила при работе с хуками? * Что такое `stateful` и `stateless` компоненты? * Что делает хук `useState`? Как обновить состояние? * Произойдет ли ререндер компонента, если сеттер установил значение, совпадающее с предыдущим? @@ -36,8 +38,6 @@ * Controlled и uncontrolled компоненты * Что это такое? Как происходит работа с инпутами? * Как задать дефолтное значение для инпута в uncontrolled компоненте? -* Что такое хуки? - * Какие существуют правила при работе с хуками? * Lifecycle of reactive effects * Что это такое? * Что такое эффекты? Что означает "синхронизация с эффектом"? From 87942acff1ef9d120ce58e15622d0c1c44bbc7f7 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 28 Nov 2024 15:58:01 +0300 Subject: [PATCH 33/93] fix(frontend/junior-2/react): state managers the wording --- frontend/junior-2/react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-2/react.md b/frontend/junior-2/react.md index be9b2e3e..30fd156b 100644 --- a/frontend/junior-2/react.md +++ b/frontend/junior-2/react.md @@ -93,7 +93,7 @@ * Как обновить Context из глубоко вложенной компоненты (т.е. пробрасывать коллбэк в таком случае - очень неудобное решение)? * Можно ли вкладывать провайдеры одного и того же Context друг в друга? Из какого провайдера при этом будут браться данные? * Почему не стоит злоупотреблять Context? - * Какие группы пакетов по управлению состоянием существуют и какие проблемы каждая решает? Какие особенности реализации используются и какие ограничения из-за этого могут накладываться? + * Какие группы стейт менеджеров существуют? * Что такое HOC? Когда хоки могут быть полезны? * Portals * Что это такое? Зачем нужны? Как использовать? From 6fbb4e4d80e5f4075153bc0a2b13cc60685d4eb2 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 28 Nov 2024 16:53:19 +0300 Subject: [PATCH 34/93] fix(frontend/junior-1/react): Lifecycle of reactive effects the wording --- frontend/junior-1/react.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/junior-1/react.md b/frontend/junior-1/react.md index 057bc5df..8c454623 100644 --- a/frontend/junior-1/react.md +++ b/frontend/junior-1/react.md @@ -42,9 +42,9 @@ * Что это такое? * Что такое эффекты? Что означает "синхронизация с эффектом"? * Для чего предназначен хук `useEffect`? Как с ним работать? + * Что такое массив зависимостей? Как он влияет на работу useEffect? + * Что может возвращать колбэк, передаваемый в useEffect? * Для чего не должен использоваться `useEffect`? Почему? - * Что может возвращать колбэк, передаваемый в `useEffect`? - * Что такое массив зависимостей? Рассказать как он влияет на работу хука на примере useEffect (в том числе на возвращаемое колбэком значение). * У вас есть несколько эффектов. Куда вы их поместите, в один общий `useEffect` или в разные? Почему? * refs * Что это такое? Зачем нужны? Как их использовать? From 7edd5af361d1cfa1ee03a3487463627ac2e39dd6 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 28 Nov 2024 17:24:17 +0300 Subject: [PATCH 35/93] fix(frontend/junior-2/react): hydration to mid-1 rendering --- frontend/junior-2/react.md | 1 - frontend/middle-1/rendering.md | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-2/react.md b/frontend/junior-2/react.md index 30fd156b..f29ce062 100644 --- a/frontend/junior-2/react.md +++ b/frontend/junior-2/react.md @@ -109,7 +109,6 @@ } } ``` -* Как отрендерить разный контент между клиентом и сервере и не нарушить процесс гидратации? ### Ресурсы diff --git a/frontend/middle-1/rendering.md b/frontend/middle-1/rendering.md index 2f1389dd..2e97f3de 100644 --- a/frontend/middle-1/rendering.md +++ b/frontend/middle-1/rendering.md @@ -5,6 +5,7 @@ * Какие есть составляющие структуры? * Как осуществляется раутинг? * Что такое гидратация (hydration)? + * Как отрендерить разный контент между клиентом и сервере и не нарушить процесс гидратации? * Какие зоны ответственности у front-server, API-server и непосредственно самого клиента в изоморфном рендеринге? Какие вычислительные нагрузки ложатся на каждую из этих частей? * Что такое streaming SSR? * Когда вы бы посоветовали заказчику использовать клиентский рендер, а когда изоморфный? From 97264489bd548d9327d2673bbfaf9c4eae25752a Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 28 Nov 2024 17:37:59 +0300 Subject: [PATCH 36/93] feat(frontend/junior-2/react): + useId --- frontend/junior-2/react.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/junior-2/react.md b/frontend/junior-2/react.md index f29ce062..bba9897a 100644 --- a/frontend/junior-2/react.md +++ b/frontend/junior-2/react.md @@ -49,6 +49,10 @@ * В какой момент может выполниться эффект и функция очистки? * Для чего предназначены хуки `useLayoutEffect`, `useInsertionEffect`, `useSyncExternalStore`? * Почему использовать `fetch` в `useEffect` - не самая хорошая идея? Какие есть альтернативы? +* `useId`: + * Для чего предназначен? Чем лучше, чем глобальный счетчик? + * Для чего не должен использоваться? + * Как задать общий префикс для всех компонентов? * Performance * Для чего в хук `useState` можно передавать функцию вместо `initialState`? * Когда передача инлайн-коллбека ухудшает производительность и почему? Пример: ` handleClick(e, user)}>` From 8e3dd8cde06b571d9d06ac740677b17a2b899f55 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 28 Nov 2024 17:45:25 +0300 Subject: [PATCH 37/93] feat(frontend/junior-3/react): reset & persist state the wording --- frontend/junior-3/react.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index e8ce6bdf..7b983031 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -124,8 +124,8 @@ ``` Предположим, что в каждом инпуте содержится какой-то текст. Если добавить в начало `list` еще один элемент, то какой из инпутов окажется пустым и почему? - * Как сбросить внутренние состояния компонента? - * Как сохранить внутренние состояния для последующего использования при необходимости скрыть результат рендера? + * Как сбросить внутренние состояния дочернего компонента? + * Как сохранить внутренние состояния дочернего комопнента при необходимости скрыть результат рендера? * Concurrent mode * Что это такое? Какие проблемы решает? Чем отличается от режима по-умолчанию? * Как перейти в данный режим? From 61acd2afb5d091674b2b64cc647d8dd5df981c51 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 28 Nov 2024 17:46:29 +0300 Subject: [PATCH 38/93] feat(frontend/junior-3/react): reset & persist state the wording --- frontend/junior-3/react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index 7b983031..e3207d1a 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -125,7 +125,7 @@ ``` Предположим, что в каждом инпуте содержится какой-то текст. Если добавить в начало `list` еще один элемент, то какой из инпутов окажется пустым и почему? * Как сбросить внутренние состояния дочернего компонента? - * Как сохранить внутренние состояния дочернего комопнента при необходимости скрыть результат рендера? + * Как сохранить внутренние состояния дочернего компонента при необходимости скрыть результат рендера? * Concurrent mode * Что это такое? Какие проблемы решает? Чем отличается от режима по-умолчанию? * Как перейти в данный режим? From 7edec0d0c8f5d47b3bd8137d6d9b0a07745caa89 Mon Sep 17 00:00:00 2001 From: Olga Klimenko Date: Mon, 2 Dec 2024 11:56:09 +0700 Subject: [PATCH 39/93] add typescript --- backend/node.js/junior-1/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/node.js/junior-1/README.md b/backend/node.js/junior-1/README.md index 4ee04a24..1bb152ed 100644 --- a/backend/node.js/junior-1/README.md +++ b/backend/node.js/junior-1/README.md @@ -1,6 +1,7 @@ # Node.js Junior 1 level - [JavaScript](../../../frontend/junior-1/js.md) +- [TypeScript](../../../frontend/junior-2/ts.md) - [Node.js](../junior-1/nodejs.md) - [Nest.js](../junior-1/nestjs.md) - [DB](../junior-1/db.md) From a8ee9597f7312d1911538c7a3897eab2c39c3a2a Mon Sep 17 00:00:00 2001 From: Olga Klimenko Date: Mon, 2 Dec 2024 11:59:34 +0700 Subject: [PATCH 40/93] fix links --- backend/node.js/junior-1/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/node.js/junior-1/README.md b/backend/node.js/junior-1/README.md index 1bb152ed..af85dcea 100644 --- a/backend/node.js/junior-1/README.md +++ b/backend/node.js/junior-1/README.md @@ -4,6 +4,6 @@ - [TypeScript](../../../frontend/junior-2/ts.md) - [Node.js](../junior-1/nodejs.md) - [Nest.js](../junior-1/nestjs.md) -- [DB](../junior-1/db.md) -- [Testing](../../shared/junior-1/testing.md) -- [Git](../../shared/junior-1/git.md) +- [DB](../../shared/junior-1/db.md) +- [Testing](../../../shared/junior-1/testing.md) +- [Git](../../../shared/junior-1/git.md) From 213ea775f3597be7c088ec59b698ec3cc74da8b3 Mon Sep 17 00:00:00 2001 From: Olga Klimenko Date: Mon, 2 Dec 2024 12:34:00 +0700 Subject: [PATCH 41/93] revert deleted db books --- backend/shared/junior-1/db.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/shared/junior-1/db.md b/backend/shared/junior-1/db.md index f13e2cd8..ad815c30 100644 --- a/backend/shared/junior-1/db.md +++ b/backend/shared/junior-1/db.md @@ -44,3 +44,13 @@ - [SQL Tutorial](https://www.w3schools.com/sql/default.asp) - [Введение в SQL и работу с базой данных](https://netology.ru/programs/vvedenie-v-sql-i-rabotu-s-bazoi-dannih#/) + + +#### Additional resources + +* [Литература с Postgrespro](https://postgrespro.ru/education/books): + * Новиков, Б. А. Основы технологий баз данных, часть 1: + * Теоретические основы БД - 2.1, 2.2 + * Моргунов, Е. П. PostgreSQL. Основы языка SQL: + * Основы SQL - главы 1-7 +* [Введение в базы данных, курс Stepik](https://stepik.org/course/551/) From e27cf91652e1437cacd21d45c8c47852c0f79e60 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Wed, 4 Dec 2024 19:26:48 +0300 Subject: [PATCH 42/93] fix(frontend/junior-1/react): refs array the wording --- frontend/junior-1/react.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/junior-1/react.md b/frontend/junior-1/react.md index 8c454623..ae65fdaa 100644 --- a/frontend/junior-1/react.md +++ b/frontend/junior-1/react.md @@ -50,7 +50,7 @@ * Что это такое? Зачем нужны? Как их использовать? * Как и для чего использовать хуки `useRef` и `useImperativeHandle`? * Что делает и зачем нужен метод `React.forwardRef`? - * Как управлять массивом ref-ов? + * Вам необходимо передать ref в каждый элемент списка, но вы не знаете заранее сколько элементов в этом списке может быть. Как поступить в таком случае? * Почему refs стоит использовать умеренно? ### Ресурсы @@ -60,3 +60,4 @@ * [React hooks: not magic, just arrays](https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e) * [Keeping Components Pure](https://react.dev//learn/keeping-components-pure) * [Lifecycle of reactive effects](https://react.dev//learn/lifecycle-of-reactive-effects) +* [How to manage a list of refs using a ref callback](https://react.dev/learn/manipulating-the-dom-with-refs#how-to-manage-a-list-of-refs-using-a-ref-callback) From 2ffa21f61e7a13e1b756da011ffeb23b6398a726 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Wed, 4 Dec 2024 19:28:33 +0300 Subject: [PATCH 43/93] fix(frontend/junior-2/react): no state managers motivation resources --- frontend/junior-2/react.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/junior-2/react.md b/frontend/junior-2/react.md index bba9897a..f76be883 100644 --- a/frontend/junior-2/react.md +++ b/frontend/junior-2/react.md @@ -122,8 +122,3 @@ * [Интересная ветка обсуждения в комментариях статьи выше](https://habr.com/ru/post/529950/comments/#comment_22380330) * [Passing Data Deeply with Context](https://react.dev//learn/passing-data-deeply-with-context) * [STATE MANAGEMENT - лучший стейт менеджер для react?](https://www.youtube.com/watch?v=AUbWwzez_Dg) -* [zustand comparison](https://zustand.docs.pmnd.rs/getting-started/comparison) -* [recoiljs motivation](https://recoiljs.org/docs/introduction/motivation/) -* [jotai comparison](https://jotai.org/docs/basics/comparison) -* [jotai concepts](https://jotai.org/docs/basics/concepts) -* [mobX principles](https://mobx.js.org/the-gist-of-mobx.html#principles) \ No newline at end of file From 86785355d428119518435d4d0c864d9a1d7f55ef Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 12 Dec 2024 14:16:00 +0300 Subject: [PATCH 44/93] feat(frontend/junior-2/react): + Thinking about UI declaratively resource --- frontend/junior-2/react.md | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/junior-2/react.md b/frontend/junior-2/react.md index f76be883..e246fce2 100644 --- a/frontend/junior-2/react.md +++ b/frontend/junior-2/react.md @@ -120,5 +120,6 @@ * [Полное руководство по useEffect](https://habr.com/ru/company/ruvds/blog/445276/) - объёмная, но очень классная статья по useEffect, которая поможет раскрыть глаза на многие вещи. Возможно придётся осилить в 2 подхода. * [Все ли вы знаете о useCallback](https://habr.com/ru/post/529950/) * [Интересная ветка обсуждения в комментариях статьи выше](https://habr.com/ru/post/529950/comments/#comment_22380330) +* [Thinking about UI declaratively](https://react.dev/learn/reacting-to-input-with-state#thinking-about-ui-declaratively) * [Passing Data Deeply with Context](https://react.dev//learn/passing-data-deeply-with-context) * [STATE MANAGEMENT - лучший стейт менеджер для react?](https://www.youtube.com/watch?v=AUbWwzez_Dg) From dce4ceb40847d514dd5406ec90a4573799f798c4 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 12 Dec 2024 14:17:23 +0300 Subject: [PATCH 45/93] feat(frontend/junior-2/react): + What are good alternatives to data fetching in Effects? resource --- frontend/junior-2/react.md | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/junior-2/react.md b/frontend/junior-2/react.md index e246fce2..e3c8c304 100644 --- a/frontend/junior-2/react.md +++ b/frontend/junior-2/react.md @@ -118,6 +118,7 @@ * [React Documentation](https://react.dev/learn) * [Полное руководство по useEffect](https://habr.com/ru/company/ruvds/blog/445276/) - объёмная, но очень классная статья по useEffect, которая поможет раскрыть глаза на многие вещи. Возможно придётся осилить в 2 подхода. +* [What are good alternatives to data fetching in Effects?](https://react.dev/reference/react/useEffect#what-are-good-alternatives-to-data-fetching-in-effects) * [Все ли вы знаете о useCallback](https://habr.com/ru/post/529950/) * [Интересная ветка обсуждения в комментариях статьи выше](https://habr.com/ru/post/529950/comments/#comment_22380330) * [Thinking about UI declaratively](https://react.dev/learn/reacting-to-input-with-state#thinking-about-ui-declaratively) From 99361363d5b1233a2f92c69cad9e2fa1b3e6bcda Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 12 Dec 2024 14:18:56 +0300 Subject: [PATCH 46/93] fix(frontend/middle-1/rendering): questions sorting --- frontend/middle-1/rendering.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/middle-1/rendering.md b/frontend/middle-1/rendering.md index 2e97f3de..ee829002 100644 --- a/frontend/middle-1/rendering.md +++ b/frontend/middle-1/rendering.md @@ -4,9 +4,9 @@ * Какие есть преимущества и недостатки? * Какие есть составляющие структуры? * Как осуществляется раутинг? +* Какие зоны ответственности у front-server, API-server и непосредственно самого клиента в изоморфном рендеринге? Какие вычислительные нагрузки ложатся на каждую из этих частей? * Что такое гидратация (hydration)? * Как отрендерить разный контент между клиентом и сервере и не нарушить процесс гидратации? -* Какие зоны ответственности у front-server, API-server и непосредственно самого клиента в изоморфном рендеринге? Какие вычислительные нагрузки ложатся на каждую из этих частей? * Что такое streaming SSR? * Когда вы бы посоветовали заказчику использовать клиентский рендер, а когда изоморфный? From 9f0364ba85b8fc775726b302f1413251fc3d0adb Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 12 Dec 2024 14:19:34 +0300 Subject: [PATCH 47/93] fix(frontend/middle-1/rendering): hydration question the wording --- frontend/middle-1/rendering.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/middle-1/rendering.md b/frontend/middle-1/rendering.md index ee829002..2eb1a2f0 100644 --- a/frontend/middle-1/rendering.md +++ b/frontend/middle-1/rendering.md @@ -6,7 +6,7 @@ * Как осуществляется раутинг? * Какие зоны ответственности у front-server, API-server и непосредственно самого клиента в изоморфном рендеринге? Какие вычислительные нагрузки ложатся на каждую из этих частей? * Что такое гидратация (hydration)? - * Как отрендерить разный контент между клиентом и сервере и не нарушить процесс гидратации? + * Как отрендерить разный контент между клиентом и сервером и не нарушить процесс гидратации? * Что такое streaming SSR? * Когда вы бы посоветовали заказчику использовать клиентский рендер, а когда изоморфный? From a47fdf90ce0d9d7b2e884ada352b5eeb9541c3fc Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 12 Dec 2024 14:21:15 +0300 Subject: [PATCH 48/93] feat(frontend/junior-3/react): - shouldComponentUpdate question --- frontend/junior-3/react.md | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index e3207d1a..7ab0ee85 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -149,7 +149,6 @@ * Как вызвать немедленное обновление состояний компонента внутри `callback`? Когда это может быть полезно? * Performance * Что такое windowing или virtualizing списков? - * Всегда ли происходит перерисовка DOM-элемента, если `shouldComponentUpdate` вернул `true`? * Synthetic Events * Что такое и зачем нужны? * Пусть на какое-то событие на `` назначено 2 обработчика: один через атрибут `on...`, а другой через `addEventListener`. From 433c1c41cfd3a052af23616536ab72f9fa031b63 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 12 Dec 2024 14:30:38 +0300 Subject: [PATCH 49/93] feat(frontend/junior-3/react): +
    --- frontend/junior-3/react.md | 304 +++++++++++++++++++++---------------- 1 file changed, 173 insertions(+), 131 deletions(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index 7ab0ee85..8fed5118 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -5,113 +5,138 @@ * Каким образом reconciliation алгоритм использует тип элемента (что происходит, если тип изменился, не изменился и т.д.)? * Являются ли следующие два примера эквивалентными? Почему? - ```jsx - if (isPacked) { - return
  • {name} ✅
  • ; - } - return
  • {name}
  • ; - ``` - - ```jsx - return ( -
  • - {isPacked ? name + ' ✅' : name} -
  • - ); - ``` +
    + Подробности: - * Произойдет ли сброс состояния `Counter`? Почему? + ```jsx + if (isPacked) { + return
  • {name} ✅
  • ; + } + return
  • {name}
  • ; + ``` - ```jsx - export default function App() { - const [isFancy, setIsFancy] = useState(false); - if (isFancy) { + ```jsx return ( -
    - - -
    +
  • + {isPacked ? name + ' ✅' : name} +
  • ); - } - return ( -
    - - -
    - ); - } - ``` + ``` + +
    + + * Произойдет ли сброс состояния `Counter`? Почему? + +
    + Подробности: + + ```jsx + export default function App() { + const [isFancy, setIsFancy] = useState(false); + if (isFancy) { + return ( +
    + + +
    + ); + } + return ( +
    + + +
    + ); + } + ``` + +
    * Произойдет ли сброс состояния `Counter`? Почему? - ```jsx - {isFancy ? ( -
    - -
    - ) : ( -
    - -
    - )} - ``` +
    + Подробности: + + ```jsx + {isFancy ? ( +
    + +
    + ) : ( +
    + +
    + )} + ``` + +
    * В чем проблемное место и как надо поступить? - ```jsx - export default function MyComponent() { - const [counter, setCounter] = useState(0); +
    + Подробности: - function MyTextField() { - const [text, setText] = useState(''); + ```jsx + export default function MyComponent() { + const [counter, setCounter] = useState(0); - return ( - setText(e.target.value)} - /> - ); - } - } - ``` - - ```jsx - return ( - <> - - - - ); - ``` + function MyTextField() { + const [text, setText] = useState(''); + + return ( + setText(e.target.value)} + /> + ); + } + } + ``` + + ```jsx + return ( + <> + + + + ); + ``` + +
    * Будет ли заново монтироваться компонент ``, если я добавлю/удалю что-то в массиве `data`? - ```jsx - - {data.map((i) => )} - - - ``` +
    + Подробности: + + ```jsx + + {data.map((i) => )} + + + ``` + +
    * Атрибут `key` * Зачем нужен? @@ -133,14 +158,19 @@ * Для чего предназначены и как использовать хуки: `useTransition` и `useDeferredValue`? * В какой последовательности сработает `console.log`, почему? - ```js - console.log(1); - startTransition(() => { - console.log(2); - setPage('/about'); - }); - console.log(3); - ``` +
    + Подробности: + + ```js + console.log(1); + startTransition(() => { + console.log(2); + setPage('/about'); + }); + console.log(3); + ``` + +
    * Batching * Что это такое? @@ -164,40 +194,52 @@ * Как HOC влияет на forwarded ref? * В чем преимущество использование HOC для получения значения из контекста перед useContext и наоборот? * with useContext: - ```typescript - type Props = { - prop1: any; - } - - const MyComp: FC = ({ prop1 }) => { - const { prop2, prop3 } = useContext(context); - ... - } - - // usage - - ``` +
    + Подробности: + + ```typescript + type Props = { + prop1: any; + } + + const MyComp: FC = ({ prop1 }) => { + const { prop2, prop3 } = useContext(context); + ... + } + + // usage + + ``` + +
    * with HOC: - ```typescript - type Props = { - prop1: any; - prop2: any; - prop3: any; - } - - const MyComp: FC = ({ prop1, prop2, prop3 }) => {...} - - // селектор тут скорее концепция, в данном случае селектор частично удовлетворяет интерфейс компонента - const selector1 = () => {...} // прокидывает в компоненту prop2 и prop3 - const MyCompWithStore1 = withSomething(selector1)(MyComp); - const selector2 = () => {...} // прокидывает в компоненту prop1 и prop3 - const MyCompWithStore2 = withSomething(selector2)(MyComp); - - - - ``` + +
    + Подробности: + + ```typescript + type Props = { + prop1: any; + prop2: any; + prop3: any; + } + + const MyComp: FC = ({ prop1, prop2, prop3 }) => {...} + + // селектор тут скорее концепция, в данном случае селектор частично удовлетворяет интерфейс компонента + const selector1 = () => {...} // прокидывает в компоненту prop2 и prop3 + const MyCompWithStore1 = withSomething(selector1)(MyComp); + const selector2 = () => {...} // прокидывает в компоненту prop1 и prop3 + const MyCompWithStore2 = withSomething(selector2)(MyComp); + + + + ``` + +
    + * Что такое Render Prop? Где и как может использоваться такой приём? * Custom Hooks * Как и для чего создавать пользовательские хуки? From 09086e13b7f2f89311256e10ac62e448c3cf6d03 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 12 Dec 2024 15:07:19 +0300 Subject: [PATCH 50/93] feat(frontend/junior-3/react): + Automatic Batching resource --- frontend/junior-3/react.md | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index 8fed5118..f8e936fc 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -253,5 +253,6 @@ * [React Fiber Architecture](https://github.com/acdlite/react-fiber-architecture) - здесь неплохо написано про reconciliation в целом, часть про детали реализации (fiber) опциональна. * [React concurrency](https://www.youtube.com/watch?v=M1OBMTYsKpo) * [Батчинг в react](https://www.youtube.com/watch?v=VfQ-qSjIalU) +* [Automatic Batching](https://react.dev/blog/2022/03/08/react-18-upgrade-guide#automatic-batching) * [React events in depth w/ Kent C. Dodds, Ben Alpert, & Dan Abramov](https://www.youtube.com/watch?v=dRo_egw7tBc) * [Getting to know React DOM’s event handling system inside out](https://medium.com/the-guild/getting-to-know-react-doms-event-handling-system-inside-out-378c44d2a5d0) From 6835d51a4d134ddfd3184fcebf2088dbfff4d618 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Fri, 13 Dec 2024 09:22:51 +0300 Subject: [PATCH 51/93] fix(frontend/junior-3/react): - some outdated batch questions --- frontend/junior-3/react.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index f8e936fc..3223cd31 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -174,8 +174,7 @@ * Batching * Что это такое? - * В каких случаях происходит? Что для этого нужно? - * Когда следует задумываться о необходимости такой оптимизации? + * В каких случаях происходит? * Как вызвать немедленное обновление состояний компонента внутри `callback`? Когда это может быть полезно? * Performance * Что такое windowing или virtualizing списков? From 9128701f87dbce7b0e64f3e73b6ee223d3b360e4 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Mon, 16 Dec 2024 16:20:43 +0300 Subject: [PATCH 52/93] fix(frontend/junior-3/data): deep data updating question the wording --- frontend/junior-3/data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-3/data.md b/frontend/junior-3/data.md index 3cc8bb96..ccad2be2 100644 --- a/frontend/junior-3/data.md +++ b/frontend/junior-3/data.md @@ -13,7 +13,7 @@ f() f({}) ``` -* Какие способы обновить глубоко вложенное значение есть? Что можно сделать, чтобы не было необходимости работать с глубоко вложенными значениями? +* Какие есть способы обновить глубоко вложенное значение? Что можно сделать, чтобы не было необходимости работать с глубоко вложенными значениями? * Утечки памяти - что это? Когда они могут возникать? Как их находить и устранять? * Какие есть способы хранения информации на клиенте? В каких случаях какой способ лучше использовать? Какие у каждого способа есть особенности? From dcd4794defd12146e023d0b2012a8681d2557166 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Mon, 16 Dec 2024 16:26:10 +0300 Subject: [PATCH 53/93] fix(frontend/junior-3/react): + "How react reconciliation works" resource --- frontend/junior-3/react.md | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index 3223cd31..523b3ac8 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -247,6 +247,7 @@ ### Ресурсы * [React Documentation](https://react.dev/learn) +* [How react reconciliation works](https://gist.github.com/zagazat/db926ec7ab69061934246a55b64913c3) * [React as a UI Runtime](https://overreacted.io/react-as-a-ui-runtime/) * [Index as a key is an anti-pattern](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318) * [React Fiber Architecture](https://github.com/acdlite/react-fiber-architecture) - здесь неплохо написано про reconciliation в целом, часть про детали реализации (fiber) опциональна. From b63a6654b28541ed27ebcca470ca4ccbfe36c346 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Tue, 17 Dec 2024 12:22:59 +0300 Subject: [PATCH 54/93] fix(frontend/junior-3/react): + code block separation --- frontend/junior-3/react.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index 523b3ac8..0375bedd 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -109,10 +109,8 @@ ); } } - ``` - - ```jsx - return ( + + return ( <> ); + } ```
    From 56c1827df4e7dcef6c35a4d7d353f09518ea92d5 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Fri, 20 Dec 2024 21:11:04 +0300 Subject: [PATCH 56/93] fix(frontend/junior-3/react): the question wording --- frontend/junior-3/react.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index 7a5bf511..7ab83982 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -25,7 +25,7 @@ - * Произойдет ли сброс состояния `Counter`? Почему? + * Произойдет ли сброс состояния `Counter` при изменении значения `IsFancy` на `true`? Почему?
    Подробности: @@ -33,6 +33,7 @@ ```jsx export default function App() { const [isFancy, setIsFancy] = useState(false); + if (isFancy) { return (
    @@ -50,6 +51,7 @@
    ); } + return (
    From 74988981e8308a3b740c18fdde7b873fb9740441 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Fri, 20 Dec 2024 21:13:34 +0300 Subject: [PATCH 57/93] fix(frontend/junior-3/react): extended code example --- frontend/junior-3/react.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index 7ab83982..ae4fcb4f 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -130,10 +130,17 @@ Подробности: ```jsx - - {data.map((i) => )} - - + const data = ['1', '2']; + + const Component = () => { + + return ( + + {data.map((i) => )} + + + ) + } ```
    From c832918a8a85c727a699aef5c88b35f1d56d2256 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Mon, 23 Dec 2024 10:33:21 +0300 Subject: [PATCH 58/93] fix(frontend/junior-1/react): useEffect with `` --- frontend/junior-1/react.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/junior-1/react.md b/frontend/junior-1/react.md index ae65fdaa..79ba8e82 100644 --- a/frontend/junior-1/react.md +++ b/frontend/junior-1/react.md @@ -42,8 +42,8 @@ * Что это такое? * Что такое эффекты? Что означает "синхронизация с эффектом"? * Для чего предназначен хук `useEffect`? Как с ним работать? - * Что такое массив зависимостей? Как он влияет на работу useEffect? - * Что может возвращать колбэк, передаваемый в useEffect? + * Что такое массив зависимостей? Как он влияет на работу `useEffect`? + * Что может возвращать колбэк, передаваемый в `useEffect`? * Для чего не должен использоваться `useEffect`? Почему? * У вас есть несколько эффектов. Куда вы их поместите, в один общий `useEffect` или в разные? Почему? * refs From b6042edc393bb5aa26f5c11790bd8367d3b286d2 Mon Sep 17 00:00:00 2001 From: Misha Yakubchuk Date: Wed, 29 Jan 2025 17:23:19 +0400 Subject: [PATCH 59/93] fix(frontend/junior-1/react): improved the sequence of questions --- frontend/junior-1/react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/junior-1/react.md b/frontend/junior-1/react.md index 79ba8e82..ffa68e37 100644 --- a/frontend/junior-1/react.md +++ b/frontend/junior-1/react.md @@ -1,6 +1,7 @@ # React * Что такое React? +* Что такое декларативное UI программирование? Чем оно отличается от императивного подхода? * Что такое React Element? Как его можно создать? Из чего он состоит? * Что будет, если передать булевые, `null` или `undefined` значения в children? * Что такое React Component? @@ -34,7 +35,6 @@ * Произойдет ли ререндер компонента, если сеттер установил значение, совпадающее с предыдущим? * Как обновить состояние из `useState` на основе предыдущего значения? Какие могут при этом возникнуть проблемы? * Что такое top-down data flow? Что является основным механизмом синхронизации нескольких компонент? - * Что такое декларативное UI программирование? Чем оно отличается от императивного подхода? * Controlled и uncontrolled компоненты * Что это такое? Как происходит работа с инпутами? * Как задать дефолтное значение для инпута в uncontrolled компоненте? From 336e75d22240bafc35efd6ec2dd92c1e1409460a Mon Sep 17 00:00:00 2001 From: quassbottle Date: Tue, 4 Feb 2025 13:29:08 +0300 Subject: [PATCH 60/93] ddd topic --- backend/shared/middle-1/ddd.md | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 backend/shared/middle-1/ddd.md diff --git a/backend/shared/middle-1/ddd.md b/backend/shared/middle-1/ddd.md new file mode 100644 index 00000000..8a1b8f1a --- /dev/null +++ b/backend/shared/middle-1/ddd.md @@ -0,0 +1,51 @@ +### Domain-Driven Design (DDD) + +#### **Strategic Design** +- Что такое Domain-Driven Design (DDD)? Каковы его цели и задачи? +- В чем заключается стратегическое проектирование в DDD? +- Какова роль эксперта предметной области в DDD? +- Что такое предметная область (Domain) и почему важно ее правильное моделирование? +- Какие бывают типы доменов: Core Domain, Supporting Domain, Generic Domain? +- Какие основные принципы лежат в основе DDD? +- Что такое Ubiquitous Language (единый язык) и почему он важен? +- Какие требования предъявляются к единому языку в рамках проекта? +- Что такое модель предметной области (Domain Model)? +- Как организовано разделение ответственности в DDD? + - Что такое Subdomain? + - Что такое Problem Domain? + - Что такое Bounded Context и почему он важен? + - В чем разница между Bounded Context и Subdomain? + - Как применяется единый язык внутри системы? +- Как организовать взаимодействие между несколькими Bounded Context внутри одной системы? + - Паттерн **Cooperation** – когда стоит использовать? + - Паттерн **Partnership** – когда стоит использовать? + - Паттерн **Shared Kernel** – когда стоит использовать? + - Паттерн **Conformist** – когда стоит использовать? + - Что такое **Anticorruption Layer (ACL)** и зачем он нужен? + - Паттерн **Open-Host Service** – когда стоит использовать? + - Паттерн **Customer-Supplier** – когда стоит использовать? + - Паттерн **Separate Ways** – когда стоит использовать? +- Что такое Context Map (карта контекстов) и зачем нужен Context Mapping? +- Почему DDD не всегда применим во всех проектах? + +#### **Tactical Design** +- Что такое тактическое проектирование и чем оно отличается от стратегического? +- В чем отличие DDD от data-oriented и service-oriented подходов? +- Что такое чистая архитектура? Из каких слоев она состоит и как применяется в DDD? +- Что такое Value Object (объект-значение)? +- Что такое Entity (сущность) и как ее правильно моделировать? +- Что такое Aggregate (агрегат) и в чем его отличие от сущности? +- Что такое Domain Event (событие предметной области) и как его использовать? +- Что такое Domain Service и в каких случаях он нужен? +- Какие архитектурные паттерны применяются в DDD? + - Какие слои входят в Layered Architecture (слоистая архитектура)? Как они связываются? Зачем они нужны? + - Что такое Ports and Adapters Architecture (архитектура портов и адаптеров)? Чем она лучше слоистой архитектуры? + - Что такое CQRS? Для чего он нужен? Как он применяется в DDD? + - Что такое Event-driven Design? Для чего он нужен? Как он применяется в DDD? +- Как DDD соотносится с архитектурой микросервисов? + +### **Ресурсы** +- Хононов Влад. *Изучаем DDD - предметно-ориентированное проектирование* +- Вернон Вон. *Реализация методов предметно-ориентированного проектирования* +- Владимир Хориков – *Domain-Driven Design: самое важное* ([Видео](https://www.youtube.com/watch?v=JOy_SNK3qj4)) +- Ричард Маркс, Форд Нил. *Фундаментальный подход к программной архитектуре: паттерны, свойства, проверенные методы* From 6787d9c6a55e55c8d3b70920859f8c73634de2bb Mon Sep 17 00:00:00 2001 From: quassbottle Date: Tue, 4 Feb 2025 13:34:09 +0300 Subject: [PATCH 61/93] fix --- backend/shared/middle-1/ddd.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/shared/middle-1/ddd.md b/backend/shared/middle-1/ddd.md index 8a1b8f1a..0bd620d2 100644 --- a/backend/shared/middle-1/ddd.md +++ b/backend/shared/middle-1/ddd.md @@ -7,7 +7,7 @@ - Что такое предметная область (Domain) и почему важно ее правильное моделирование? - Какие бывают типы доменов: Core Domain, Supporting Domain, Generic Domain? - Какие основные принципы лежат в основе DDD? -- Что такое Ubiquitous Language (единый язык) и почему он важен? +- Что такое Ubiquitous Language (единый язык). Почему он важен в DDD-проектах? - Какие требования предъявляются к единому языку в рамках проекта? - Что такое модель предметной области (Domain Model)? - Как организовано разделение ответственности в DDD? @@ -25,18 +25,18 @@ - Паттерн **Open-Host Service** – когда стоит использовать? - Паттерн **Customer-Supplier** – когда стоит использовать? - Паттерн **Separate Ways** – когда стоит использовать? -- Что такое Context Map (карта контекстов) и зачем нужен Context Mapping? +- Что такое Context Map (карта контекстов). Зачем нужен Context Mapping? - Почему DDD не всегда применим во всех проектах? #### **Tactical Design** - Что такое тактическое проектирование и чем оно отличается от стратегического? - В чем отличие DDD от data-oriented и service-oriented подходов? - Что такое чистая архитектура? Из каких слоев она состоит и как применяется в DDD? -- Что такое Value Object (объект-значение)? -- Что такое Entity (сущность) и как ее правильно моделировать? -- Что такое Aggregate (агрегат) и в чем его отличие от сущности? -- Что такое Domain Event (событие предметной области) и как его использовать? -- Что такое Domain Service и в каких случаях он нужен? +- Что такое Value Object (объект-значение)? Для чего применяется? +- Что такое Entity (сущность)? +- Что такое Aggregate (агрегат). В чем его отличие от сущности? +- Что такое Domain Events (события предметной области). Зачем и как их использовать? +- Что такое Domain Service. В каких случаях он нужен? - Какие архитектурные паттерны применяются в DDD? - Какие слои входят в Layered Architecture (слоистая архитектура)? Как они связываются? Зачем они нужны? - Что такое Ports and Adapters Architecture (архитектура портов и адаптеров)? Чем она лучше слоистой архитектуры? From cd7941d03f9adcb0ed8b4e9658ff342c5fd6bce2 Mon Sep 17 00:00:00 2001 From: quassbottle Date: Tue, 4 Feb 2025 14:12:28 +0300 Subject: [PATCH 62/93] fix video url --- backend/shared/middle-1/ddd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/shared/middle-1/ddd.md b/backend/shared/middle-1/ddd.md index 0bd620d2..9b708730 100644 --- a/backend/shared/middle-1/ddd.md +++ b/backend/shared/middle-1/ddd.md @@ -47,5 +47,5 @@ ### **Ресурсы** - Хононов Влад. *Изучаем DDD - предметно-ориентированное проектирование* - Вернон Вон. *Реализация методов предметно-ориентированного проектирования* -- Владимир Хориков – *Domain-Driven Design: самое важное* ([Видео](https://www.youtube.com/watch?v=JOy_SNK3qj4)) +- [Владимир Хориков – *Domain-Driven Design: самое важное*](https://www.youtube.com/watch?v=JOy_SNK3qj4) - Ричард Маркс, Форд Нил. *Фундаментальный подход к программной архитектуре: паттерны, свойства, проверенные методы* From f4c10560cbcf7647cb9284490e33fd241677789f Mon Sep 17 00:00:00 2001 From: quassbottle <48488634+quassbottle@users.noreply.github.com> Date: Wed, 5 Feb 2025 20:07:25 +0300 Subject: [PATCH 63/93] add anemic question --- backend/shared/middle-1/ddd.md | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/shared/middle-1/ddd.md b/backend/shared/middle-1/ddd.md index 9b708730..c146c150 100644 --- a/backend/shared/middle-1/ddd.md +++ b/backend/shared/middle-1/ddd.md @@ -35,6 +35,7 @@ - Что такое Value Object (объект-значение)? Для чего применяется? - Что такое Entity (сущность)? - Что такое Aggregate (агрегат). В чем его отличие от сущности? +- Что такое анемичная модель? Почему это плохо? Как с этим бороться? - Что такое Domain Events (события предметной области). Зачем и как их использовать? - Что такое Domain Service. В каких случаях он нужен? - Какие архитектурные паттерны применяются в DDD? From 3a7dbb8970a4248714aaf3110ce7e9748556b517 Mon Sep 17 00:00:00 2001 From: quassbottle <48488634+quassbottle@users.noreply.github.com> Date: Wed, 5 Feb 2025 20:08:50 +0300 Subject: [PATCH 64/93] add solution and problem space --- backend/shared/middle-1/ddd.md | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/shared/middle-1/ddd.md b/backend/shared/middle-1/ddd.md index c146c150..375189c1 100644 --- a/backend/shared/middle-1/ddd.md +++ b/backend/shared/middle-1/ddd.md @@ -16,6 +16,7 @@ - Что такое Bounded Context и почему он важен? - В чем разница между Bounded Context и Subdomain? - Как применяется единый язык внутри системы? +- Что такое Problem и Solution Space? - Как организовать взаимодействие между несколькими Bounded Context внутри одной системы? - Паттерн **Cooperation** – когда стоит использовать? - Паттерн **Partnership** – когда стоит использовать? From f29a02fd490a2ea081455c5502526f4f389350d0 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Thu, 27 Feb 2025 11:28:21 +0300 Subject: [PATCH 65/93] feat(frontend/middle-1): update resources --- frontend/middle-1/solid.md | 5 +++++ frontend/middle-1/testing.md | 11 ++++------- frontend/middle-1/typescript.md | 2 +- shared/middle/basic-design-principles.md | 2 ++ 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/frontend/middle-1/solid.md b/frontend/middle-1/solid.md index fd9c3c96..f0a0f56c 100644 --- a/frontend/middle-1/solid.md +++ b/frontend/middle-1/solid.md @@ -21,6 +21,8 @@ Learn how to design complex systems according to engineering heuristics gathered * [Basic design principles](./design.md) * [OOP](./oop.md) +## Common resources +* [Do the SOLID principles apply to Functional Programming?](https://dev.to/patferraggi/do-the-solid-principles-apply-to-functional-programming-56lm) ## The Single Responsibility Principle (SRP) * What is The Single Responsibility Principle? @@ -39,6 +41,8 @@ Learn how to design complex systems according to engineering heuristics gathered #### Resources * [The Single Responsibility Principle](https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html) * [Think you understand the Single Responsibility Principle?](https://hackernoon.com/you-dont-understand-the-single-responsibility-principle-abfdd005b137) +* [Single Responsibility Principle revisited](https://thevaluable.dev/single-responsibility-principle-revisited/) +* [DRY vs SRP](https://www.geeksforgeeks.org/dont-repeat-yourselfdry-in-software-development/#dont-repeat-yourself-dry-vs-single-responsibility-principle-srp) * [On the Criteria To Be Used in Decomposing Systems into Modules](https://www.win.tue.nl/~wstomv/edu/2ip30/references/criteria_for_modularization.pdf) (closely related to SRP) * [Review of "On the criteria to be used in decomposing systems into modules"](https://blog.acolyer.org/2016/09/05/on-the-criteria-to-be-used-in-decomposing-systems-into-modules/) * [The Modular Structure of Complex Systems](https://www.researchgate.net/publication/2814490_The_Modular_Structure_of_Complex_Systems) @@ -88,6 +92,7 @@ Learn how to design complex systems according to engineering heuristics gathered #### Resources * [The Interface Segregation Principle — it’s confused](https://medium.com/@jim_ej/the-interface-segregation-principle-its-confused-aa856de97d36) +* [Interface Segregation Principle: Everything You Need to Know](https://reflectoring.io/interface-segregation-principle/) ## The Dependency Inversion Principle (DIP) diff --git a/frontend/middle-1/testing.md b/frontend/middle-1/testing.md index c656390c..c3fe0303 100644 --- a/frontend/middle-1/testing.md +++ b/frontend/middle-1/testing.md @@ -13,13 +13,10 @@ ### Ресурсы -* [Test first by R. Martin](https://blog.cleancoder.com/uncle-bob/2013/09/23/Test-first.html) -* [5 Questions Every Unit Test Must Answer by E. Elliott](https://medium.com/javascript-scene/what-every-unit-test-needs-f6cd34d9836d) -* [Unit Tests, How to Write Testable Code and Why it Matters](https://www.toptal.com/qa/how-to-write-testable-code-and-why-it-matters) -* [UnitTest by M. Fowler](https://martinfowler.com/bliki/UnitTest.html) -* [Unit Tests from XP](http://www.extremeprogramming.org/rules/unittests.html) -* [Test Reviews Vs. Code Reviews - Some Helpful Tips](https://osherove.com/blog/2007/3/13/test-reviews-vs-code-reviews-some-helpful-tips.html) * [Types and Tests](https://blog.cleancoder.com/uncle-bob/2017/01/13/TypesAndTests.html) -* [Mocks Aren't Stubs](https://www.martinfowler.com/articles/mocksArentStubs.html) * [We don't write tests. There just isn't time for luxuries.](https://www.jamesgolick.com/2007/8/22/we-dont-write-tests-there-just-isnt-time-for-luxuries.html) +* [Test first by R. Martin](https://blog.cleancoder.com/uncle-bob/2013/09/23/Test-first.html) * [Юнит-тестирование для чайников](https://habr.com/en/post/169381/) +* [UnitTest by M. Fowler](https://martinfowler.com/bliki/UnitTest.html) +* [Mocks Aren't Stubs](https://www.martinfowler.com/articles/mocksArentStubs.html) +* [Unit Tests, How to Write Testable Code and Why it Matters](https://www.toptal.com/qa/how-to-write-testable-code-and-why-it-matters) diff --git a/frontend/middle-1/typescript.md b/frontend/middle-1/typescript.md index 9d5ea9bf..89f771ff 100644 --- a/frontend/middle-1/typescript.md +++ b/frontend/middle-1/typescript.md @@ -36,6 +36,6 @@ * [Programming TypeScript by Boris Cherny. Chapter 6.](https://learning.oreilly.com/library/view/programming-typescript/9781492037644/ch06.html) * [Reference Checker Widening Narrowing](https://github.com/microsoft/TypeScript/wiki/Reference-Checker-Widening-Narrowing) * [Everyday TypeScript: Type widening](https://www.executeprogram.com/courses/everyday-typescript/lessons/type-widening) -* [What are covariance and contravariance?](https://www.stephanboyer.com/post/132/what-are-covariance-and-contravariance) +* [Covariance and Contravariance in TypeScript](https://dmitripavlutin.com/typescript-covariance-contravariance/) * [What the heck is polymorphism? (только главы до Row polymorphism включительно)](https://dev.to/jvanbruegge/what-the-heck-is-polymorphism-nmh) * [Discussion: Typed, modular macros for OCaml, thread about row polymorphism](https://news.ycombinator.com/item?id=13046210) diff --git a/shared/middle/basic-design-principles.md b/shared/middle/basic-design-principles.md index e4a1b550..4784ec0a 100644 --- a/shared/middle/basic-design-principles.md +++ b/shared/middle/basic-design-principles.md @@ -52,6 +52,7 @@ * [Abstraction, Encapsulation, and Information Hiding](http://www.tonymarston.co.uk/php-mysql/abstraction.txt) * [Difference between Abstraction and Encapsulation](https://www.guru99.com/difference-between-abstraction-and-encapsulation.html#2) +* [Coupling & Cohesion](https://www.geeksforgeeks.org/software-engineering-coupling-and-cohesion/) * [Cohesion](https://www.chegg.com/learn/computer-science/computer-software/module-cohesion) * [Coupling](https://www.chegg.com/learn/computer-science/computer-software/module-coupling) * [The DRY Principle Explained: Its Benefit and Cost with Examples](https://thevaluable.dev/dry-principle-explained/) [[Перевод](https://habr.com/ru/company/mailru/blog/349978/)] @@ -61,6 +62,7 @@ * [A Detailed Explanation of The KISS Principle in Software](https://thevaluable.dev/kiss-principle-explained/) * [Simple Made Easy — talk of Rich Hickey](https://www.infoq.com/presentations/Simple-Made-Easy/) * [The Art of Separation of Concerns](http://aspiringcraftsman.com/2008/01/03/art-of-separation-of-concerns/) +* [Separation of Concerns - SoC](https://www.geeksforgeeks.org/separation-of-concerns-soc/) * [Cross cutting concern example on SO](https://stackoverflow.com/questions/23700540/cross-cutting-concern-example) * [Cross cutting concern on Wiki](https://en.wikipedia.org/wiki/Cross-cutting_concern) * [Coarse-grained vs fine-grained on SO](https://stackoverflow.com/questions/3766845/coarse-grained-vs-fine-grained) From cc8decc1f76101655e176ec1222d1b45197d5e75 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Fri, 28 Feb 2025 11:21:39 +0300 Subject: [PATCH 66/93] feat(frontend/middle-1): + questions --- .../middle-1/algorithmsAndDataStructures.md | 4 +++ frontend/middle-1/fp.md | 28 ++++++++++++++----- frontend/middle-1/solid.md | 2 ++ frontend/middle-1/testing.md | 1 + frontend/middle-1/typescript.md | 2 ++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/frontend/middle-1/algorithmsAndDataStructures.md b/frontend/middle-1/algorithmsAndDataStructures.md index b6460a58..15c7d0ba 100644 --- a/frontend/middle-1/algorithmsAndDataStructures.md +++ b/frontend/middle-1/algorithmsAndDataStructures.md @@ -22,6 +22,7 @@ * перечислите недостатки и преимущества; * приведите алгоритмы использующие эту парадигму. * Brute-force +* Greedy * Divide and Conquer * Dynamic Programming @@ -33,7 +34,9 @@ * Что значит сложность худшего случая? Лучшего? Среднего? * Дайте опредление для каждого из обозначений: * О (Big Oh) + * o (Little-o) * Ω (Big Omega) + * ω (Little-Omega) * θ (Big Theta) * Какое практическое применение имеет оценка сложности алгоритмов? @@ -43,6 +46,7 @@ 3. [Horowitz and Sahani Fundamentals Of Computer Algorithms 2nd edition](https://www.academia.edu/39717003/Horowitz_and_sahani_fundamentals_of_computer_algorithms_2nd_edition) Chapters 1, 3, 4, 5 4. [Essential Algorithms: A Practical Approach to Computer Algorithms](https://www.google.com/search?source=hp&ei=MZCJXu-dLZeDk74P6ciQuAo&q=essential+algorithms+a+practical+approach+&oq=essential+algorithms+a+practical+approach+&gs_lcp=CgZwc3ktYWIQAzICCAAyAggAMgYIABAWEB4yBggAEBYQHjIGCAAQFhAeMgYIABAWEB4yBggAEBYQHjoFCAAQgwE6BAgAEAo6CQgAEAoQRhD_AToECAAQDToFCAAQzQJKMggXEi4wZzkwZzEwN2cxMTBnMTA2ZzEwNmcxMDlnMTE3ZzExNmcxMTNnMTQ5ZzBnMTExSh0IGBIZMGcxZzFnMWcxZzFnMWcxZzFnMWczZzBnMlBHWN0hYI0saABwAHgAgAGtAYgBzAuSAQM4LjaYAQCgAQGqAQdnd3Mtd2l6&sclient=psy-ab&ved=0ahUKEwiv-uvj6NDoAhWXwcQBHWkkBKcQ4dUDCAc&uact=5) Chapter 1 5. [Introduction to Asymptotic Analysis](http://www.cs.cornell.edu/courses/cs312/2004fa/lectures/lecture16) +6. [Big-O, Little-o, Big-Omega, Little-Omega, and Theta notations](https://github.com/Qingquan-Li/blog/issues/274) ## Данные diff --git a/frontend/middle-1/fp.md b/frontend/middle-1/fp.md index 8ae05c27..68928cc2 100644 --- a/frontend/middle-1/fp.md +++ b/frontend/middle-1/fp.md @@ -24,13 +24,13 @@ const curried = curry(abc); - curried(1, 2, 3); // => [1, 2, 3] - curried(1)(2)(3); // => [1, 2, 3] - curried(1, 2)(3); // => [1, 2, 3] - curried(_, 2, 3)(1); // => [1, 2, 3] - curried(1, _, 3)(2); // => [1, 2, 3] - curried(1, _, _)(2, 3); // => [1, 2, 3] - curried(_, _, 3)(1)(2); // => [1, 2, 3] + console.log(curried(1, 2, 3)); // => [1, 2, 3] + console.log(curried(1)(2)(3)); // => [1, 2, 3] + console.log(curried(1, 2)(3)); // => [1, 2, 3] + console.log(curried(_, 2, 3)(1)); // => [1, 2, 3] + console.log(curried(1, _, 3)(2)); // => [1, 2, 3] + console.log(curried(1, _, _)(2, 3)); // => [1, 2, 3] + console.log(curried(_, _, 3)(1)(2)); // => [1, 2, 3] ``` * Композиция функций @@ -38,6 +38,20 @@ * Для чего используется? * Что такое `pipe`? * Как реализовать функцию `compose`? +
    + Подробности: + + ```javascript + function addOne(acc){ return acc + 1 } + function addTwo(acc){ return acc + 2 } + function addThree(acc){ return acc + 3 } + + const composed = compose(addThree,addTwo,addOne); + + console.log(composed(0)) // 6 + ``` + +
    * Point-free style * Что такое? * Какие может дать преимущества? diff --git a/frontend/middle-1/solid.md b/frontend/middle-1/solid.md index f0a0f56c..8f839d58 100644 --- a/frontend/middle-1/solid.md +++ b/frontend/middle-1/solid.md @@ -104,6 +104,7 @@ Learn how to design complex systems according to engineering heuristics gathered * How is the DIP related to the OCP? * Where should abstraction be declared that connects high-level and low-level modules? Can it be declared in a low-level module and then be imported into a high-level one? * Does library violate the DIP (for example React) if it is both concrete and widely used in your project? +* What techniques allow you to implement DIP? * What is the Stable Dependencies Principle (SDP) and how is it related to the DIP? * What is the stability metric and what does it measure? * Why do modules with high stability tend to be less volatile? @@ -112,6 +113,7 @@ Learn how to design complex systems according to engineering heuristics gathered * What is The Stable Abstractions Principle and how is it related to the SDP? * Why Instability and Abstraction metrics should be balanced? * What is the Main Sequence where the sum of Instability and Abstraction is 1? +* Is the DIP the same as DI, or IoC? * Can the DIP also be useful for a project written in FP style? diff --git a/frontend/middle-1/testing.md b/frontend/middle-1/testing.md index c3fe0303..6f1bf2b6 100644 --- a/frontend/middle-1/testing.md +++ b/frontend/middle-1/testing.md @@ -4,6 +4,7 @@ * Являются ли типы полной заменой unit-тестам? Почему? * Что такое end-to-end тесты? В чём отличие от интеграционных? * Когда тесты действительно замедляют разработку, а когда ускоряют? +* Что значат волшебные слова: "Given, When, and Then" для тестов? Каков порядок будет для написания кода? * Являются ли тесты полноправной частью системы и кодовой базы? * Что такое Test Double? Что такое Fake, Mock, Stub? * Какая разница между тестированием с behavior verification и со state verification? diff --git a/frontend/middle-1/typescript.md b/frontend/middle-1/typescript.md index 89f771ff..69b73000 100644 --- a/frontend/middle-1/typescript.md +++ b/frontend/middle-1/typescript.md @@ -8,6 +8,7 @@ * Когда в TS проявляется Covariance? Когда Contravariance? * Если в функцию передать коллбек, который принимает другой коллбек, то параметры будут проявлять Covariance или Contravariance (вывести на примере самостоятельно)? * Если бы объекты и классы TS были Invariant, то как бы это повлияло на type safety и на удобство разработки? + * Как задать конкретный variance у generic типа? * Почему TS считает compatible тип функции с меньшим количество аргументов ```typescript ((a: number) => 0; assignable to (b: number, s: string) => 0;) @@ -32,6 +33,7 @@ * [How can a statically typed language support duck typing?](https://softwareengineering.stackexchange.com/questions/252984/how-can-a-statically-typed-language-support-duck-typing) * [Flavoring: Flexible Nominal Typing for TypeScript](https://spin.atomicobject.com/2018/01/15/typescript-flexible-nominal-typing/) * [Wiki: Variance (определение)](https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)) [RUS](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82%D0%BD%D0%BE%D1%81%D1%82%D1%8C_%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%B0%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82%D0%BD%D0%BE%D1%81%D1%82%D1%8C_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)) +* [Generics Variance Annotations](https://www.typescriptlang.org/docs/handbook/2/generics.html#variance-annotations) * [Номинативная типизация в TypeScript или как защитить свой интерфейс от чужих идентификаторов](https://habr.com/ru/post/446768/) * [Programming TypeScript by Boris Cherny. Chapter 6.](https://learning.oreilly.com/library/view/programming-typescript/9781492037644/ch06.html) * [Reference Checker Widening Narrowing](https://github.com/microsoft/TypeScript/wiki/Reference-Checker-Widening-Narrowing) From 4c5e21fb5b6195147379faad252083735f629613 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Fri, 28 Feb 2025 12:49:07 +0300 Subject: [PATCH 67/93] feat(frontend/junior-3): + questions --- frontend/junior-3/api.md | 2 +- frontend/junior-3/js.md | 27 +++++++++++++++++++++++++++ frontend/junior-3/react.md | 3 ++- frontend/junior-3/security.md | 6 ++++++ frontend/junior-3/ts.md | 3 +++ shared/junior-3/git.md | 1 + 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/frontend/junior-3/api.md b/frontend/junior-3/api.md index a1f426e6..66c39f8d 100644 --- a/frontend/junior-3/api.md +++ b/frontend/junior-3/api.md @@ -14,5 +14,5 @@ * [JSON API – работаем по спецификации](https://habr.com/ru/companies/oleg-bunin/articles/433322/) * [JSON API Specification](http://jsonapi.org/format/) * [JSON RPC Specification](https://www.jsonrpc.org/specification) -* [GraphQL Specification](https://facebook.github.io/graphql/) +* [GraphQL Specification](https://spec.graphql.org/) * [Introduction to GraphQL](https://graphql.org/learn/) diff --git a/frontend/junior-3/js.md b/frontend/junior-3/js.md index cac5ad44..94c9787e 100644 --- a/frontend/junior-3/js.md +++ b/frontend/junior-3/js.md @@ -36,7 +36,34 @@ * Как работают опережающие и ретроспективные проверки? * Решить задачи: * Написать регулярное выражение по переводу Function Expression в Function Declaration. +
    + Подробности: + + ```js + console.log(toFunctionDeclaration('const sayHi = function (who) { alert(`Hello, ${who}`); }')) // function sayHi(who) { alert(`Hello, ${who}`); } + + function toFunctionDeclaration(functionExpression:string){ + return + } + ``` + +
    + * Написать регулярное выражение по переводу Function Declaration в Function Expression. + +
    + Подробности: + + ```js + console.log(toFunctionExpression('function sayHi(who) { alert(`Hello, ${who}`); }')) // const sayHi = function (who) { alert(`Hello, ${who}`); } + + function toFunctionExpression(functionDeclaration:string){ + return + } + ``` + +
    + * Написать регулярное выражение для поиска всех команд Телеграма в сообщении (примеры: `/help`, `/start`, `/active_orders`, `/order123`). Учесть, что команд в подстроке может быть несколько. ## Итераторы и генераторы diff --git a/frontend/junior-3/react.md b/frontend/junior-3/react.md index ae4fcb4f..e721bf17 100644 --- a/frontend/junior-3/react.md +++ b/frontend/junior-3/react.md @@ -2,7 +2,7 @@ * Reconciliation * Что такое? Какую функцию выполняет? - * Каким образом reconciliation алгоритм использует тип элемента (что происходит, если тип изменился, не изменился и т.д.)? + * Что для reconciliation алгоритма является типом элемента? Каким образом reconciliation алгоритм использует тип элемента (что происходит, если тип изменился, не изменился и т.д.)? * Являются ли следующие два примера эквивалентными? Почему?
    @@ -187,6 +187,7 @@ * Что такое windowing или virtualizing списков? * Synthetic Events * Что такое и зачем нужны? + * Какие всплывают? Какие есть особенности всплытия у разных типов событий? * Пусть на какое-то событие на `` назначено 2 обработчика: один через атрибут `on...`, а другой через `addEventListener`. * В чем разница между добавлением обработчиков первым и вторым способом? * В каком порядке могут выполняться обработчики? От чего это зависит? diff --git a/frontend/junior-3/security.md b/frontend/junior-3/security.md index e15ecb49..cf3bd1ce 100644 --- a/frontend/junior-3/security.md +++ b/frontend/junior-3/security.md @@ -1,6 +1,11 @@ # Безопасность * Атаки + * Supply chain attacks + * Что такое? + * Как работает? + * Из-за чего чаще всего происходит? + * Какие есть способы предотвратить (необязательно перечислять все)? * XSS (Cross-site scripting) * Что такое? * Как работает? @@ -25,6 +30,7 @@ ### Ресурсы +* [Supply chain attacks](https://nodejs.org/en/learn/getting-started/security-best-practices#supply-chain-attacks) * [Основы XSS](https://hackware.ru/?p=1174) * [XSS](https://portswigger.net/web-security/cross-site-scripting) * [XSS Game](https://xss-game.appspot.com/level1) diff --git a/frontend/junior-3/ts.md b/frontend/junior-3/ts.md index b7b4253c..3dca443f 100644 --- a/frontend/junior-3/ts.md +++ b/frontend/junior-3/ts.md @@ -53,6 +53,7 @@ * Теперь сделайте так, чтобы в объекте `survivedAvengers` ключи типа `Head` были опциональными. * Теперь сделайте так, чтобы в объекте `survivedAvengers` ключи типа `Head` были опциональными, за исключением ключей, переданных в дженерик, т.е. общие ключи из `Head` и `T` должны быть обязательными, а все остальные ключи из `Head` должны быть опциональными. * Каково назначение нижеперечисленных типов? + * `Awaited` * `Partial` * `Readonly` * `Required` @@ -65,6 +66,7 @@ * `ReturnType` * `Parameters` * `InstanceType` + * `NoInfer` * `ThisType` * Для чего предназначены Conditional Types? * Как проявляется дистрибутивность в Conditional Types? @@ -75,6 +77,7 @@ ### Ресурсы * [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/advanced-types.html) +* [Перегрузка функций в TypeScript](https://habr.com/ru/companies/otus/articles/688270/) * [How 2 TypeScript: Serious business with TypeScript's infer keyword](https://dev.to/miracleblue/how-2-typescript-serious-business-with-typescripts-infer-keyword-40i5) * [Conditional Types in TypeScript](https://mariusschulz.com/blog/conditional-types-in-typescript) * [Recursive Type Aliases](https://dev.to/busypeoples/notes-on-typescript-recursive-types-and-immutability-5ck1) diff --git a/shared/junior-3/git.md b/shared/junior-3/git.md index bbb03b06..8f080bd0 100644 --- a/shared/junior-3/git.md +++ b/shared/junior-3/git.md @@ -15,6 +15,7 @@ * `cherry-pick` * `filter-branch`/`git-filter-repo` * `rebase` + * Как ведет себя если есть коммиты слияния? * Что такое интерактивный режим ребейза? Что он позволяет делать? * Какие есть опасности при использовании ребейза? * Что делают, как пользоваться, и когда бывают полезны команды: From 43ec586b460e5f8ad201ce1e7e34a27b4c611ef8 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Fri, 28 Feb 2025 12:50:54 +0300 Subject: [PATCH 68/93] feat(frontend/junior-1): + questions --- frontend/junior-1/css.md | 1 + frontend/junior-1/react.md | 1 + 2 files changed, 2 insertions(+) diff --git a/frontend/junior-1/css.md b/frontend/junior-1/css.md index a6160f18..49534ecf 100644 --- a/frontend/junior-1/css.md +++ b/frontend/junior-1/css.md @@ -83,6 +83,7 @@ * `transition-duration` * `transition-property` * `transition-timing-function` + * `transition-behavior` * Можно ли задать несколько анимаций для элемента? * Трансформации * Что делает свойство `transform`? Какие значения ему можно задавать? diff --git a/frontend/junior-1/react.md b/frontend/junior-1/react.md index ffa68e37..c0ab894b 100644 --- a/frontend/junior-1/react.md +++ b/frontend/junior-1/react.md @@ -4,6 +4,7 @@ * Что такое декларативное UI программирование? Чем оно отличается от императивного подхода? * Что такое React Element? Как его можно создать? Из чего он состоит? * Что будет, если передать булевые, `null` или `undefined` значения в children? + * В чем разница между `ReactElement`, `JSX.Element`, `ReactNode`? Какой тип выбрать для типизации значения на рендер? * Что такое React Component? * Что такое JSX и зачем он нужен? * Почему атрибуты в JSX пишутся, используя camelCase (например, `tabIndex`, а не `tab-index`)? Почему `className`, а не `class`? From bd7f3905f5b784d00f1655f4d5a61b5a0ca88ed9 Mon Sep 17 00:00:00 2001 From: Nikita Zaitsev Date: Fri, 28 Feb 2025 20:54:47 +0300 Subject: [PATCH 69/93] feat(frontend): + practice mark --- frontend/junior-1/css.md | 2 +- frontend/junior-1/html.md | 2 +- frontend/junior-1/js.md | 6 +++--- frontend/junior-1/react.md | 20 ++++++++++++++++++-- frontend/junior-2/html.md | 2 +- frontend/junior-2/js.md | 4 ++-- frontend/junior-2/react.md | 2 +- frontend/junior-2/ts.md | 6 +++--- frontend/junior-3/css.md | 2 +- frontend/junior-3/data.md | 2 +- frontend/junior-3/js.md | 2 +- frontend/junior-3/ts.md | 4 ++-- frontend/middle-1/fp.md | 4 ++-- 13 files changed, 37 insertions(+), 21 deletions(-) diff --git a/frontend/junior-1/css.md b/frontend/junior-1/css.md index 49534ecf..09d373c9 100644 --- a/frontend/junior-1/css.md +++ b/frontend/junior-1/css.md @@ -96,7 +96,7 @@ * Как пользоваться `vh`, `vw`, `vmin`, `vmax`? * Что делает свойство `object-fit`? * Что делает свойство `aspect-ratio`? -* Как стилизовать чекбокс? +* Как стилизовать чекбокс(практика)? * Как прижать футер к низу страницы (назвать хотя бы два способа)? * Как отцентровать элемент по горизонтали (назвать хотя бы три способа)? * Как отцентровать элемент по вертикали (назвать хотя бы три способа)? diff --git a/frontend/junior-1/html.md b/frontend/junior-1/html.md index e4a0c8b5..a4730387 100644 --- a/frontend/junior-1/html.md +++ b/frontend/junior-1/html.md @@ -36,7 +36,7 @@ * Как препроцессоры помогают избежать боли с дублированием названий в коде? * Какие альтернативы есть БЭМ и в чем сила/слабость каждого? Знать хотя бы 2 альтернативы данному подходу, плюсы/минусы подходов. * Что такое миксы в БЭМе и какие особенности работы с ними есть? - * Как бы отрефакторили данный код: + * Как бы отрефакторили данный код(практика): ```html
    diff --git a/frontend/junior-1/js.md b/frontend/junior-1/js.md index 2b45ef20..ccb26e51 100644 --- a/frontend/junior-1/js.md +++ b/frontend/junior-1/js.md @@ -85,7 +85,7 @@ * Как получить все аргументы функции (включая те, что не объявлены, но все-таки были переданы)? * Что такое рекурсия? Когда удобно её использовать? * Что такое замыкания, и в каких случаях они могут быть полезны? Как сохранить состояние с помощью замыкания, и для чего это состояние может быть использовано? -* Как реализовать функцию `bind`? +* Как реализовать функцию `bind`(практика)? * Решить такую вот проблему: пускай у нас есть массив ссылок, и наша задача — сделать так, чтобы при клике на каждую выводился `alert`ом ее порядковый номер. Первое решение, что приходит в голову, выглядит так: ```javascript for (var i = 0; i < links.length; i++) { @@ -94,7 +94,7 @@    } } ``` - На деле же оказывается, что при клике на любую ссылку выводится одно и то же число — значение `links.length`. Почему так происходит и как эту гадость исправить? + На деле же оказывается, что при клике на любую ссылку выводится одно и то же число — значение `links.length`. Почему так происходит и как эту гадость исправить(практика)? * Что такое callback (функция обратного вызова)? Когда они обычно применяются? * Что такое каррирование? * Что такое частичное применение? @@ -120,7 +120,7 @@ * Как создать объект, который ни от чего не наследуется? * Какие 3 (как минимум) способа есть отнаследоваться в JavaScript-е? В чем отличия и нюансы? * Как объявить приватное поле класса в JS? -* Как в переопределенном методе у наследующего класса вызвать переопределяемый метод родительского? +* Как в переопределенном методе у наследующего класса вызвать переопределяемый метод родительского(практика)? Пример псевдокода: ```javascript class Person diff --git a/frontend/junior-1/react.md b/frontend/junior-1/react.md index c0ab894b..278c3090 100644 --- a/frontend/junior-1/react.md +++ b/frontend/junior-1/react.md @@ -9,7 +9,7 @@ * Что такое JSX и зачем он нужен? * Почему атрибуты в JSX пишутся, используя camelCase (например, `tabIndex`, а не `tab-index`)? Почему `className`, а не `class`? * Почему название компоненты, которая используется в JSX, нужно писать с большой буквы? - * Написать аналог с `React.createElement`: + * Написать аналог с `React.createElement`(практика): ```javascript