Работа мечты
- Amazon
- Apple
- Netflix
- Microsoft
Мотивация
Характер + воспитание + обстоятельства = воля + мораль + закалка
- Отрицание
- Гнев
- Торг
- Депрессия
- Принятие
Один работник заходит к хозяину и спрашивает: – А почему ты платишь мне всего рубль в неделю, в то время как Елисею – пятнадцать? Хозяин смотрит в окно и говорит: – Слышу, кто-то едет. Нам сена на зиму нужно купить. Выйди-ка, посмотри, не сено ли везут. Вышел работник. Зашел и говорит: – Правда, сено. – А не знаешь, откуда? Может, с Лукьяновских лугов? – Не знаю. – Так сходи и спроси. Пошел тот. Снова входит: – Точно, с Лукьяновских. – А сено какого укоса – первого или второго? – Не знаю. – Так сходи, узнай! Вышел работник. Возвращается: – Хозяин! Первого укоса! – А не знаешь, почем? – Не знаю. – Так сходи, узнай. Сходил. Вернулся и говорит: – Хозяин! По двадцать рублей. – А дешевле не дают? – Не знаю. В этот момент входит Елисей и говорит: – Хозяин! Мимо везли сено с Лукьяновских лугов первого укоса. Просили по 20 рублей. Сторговались по 17 за воз. Я их загнал во двор, сейчас разгружают. Хозяин поворачивается к первому: – Теперь ты понял, почему тебе платят 1 рубль, а Елисею – 15?
Compensations
- https://www.levels.fyi/
- http://www.tax-rates.org/income-tax-calculator/?ref=nav_income - налоговый калькулятор США
Jobs Websites
- https://linkedin.com
- https://indeed.com
- https://glassdoor.com/
- https://www.toptal.com/
- https://www.crunchbase.com/
Подготовка
- Cracking the coding interview
- Алгоритмы. Построение и анализ | Кормен Томас Х., Лейзерсон Чарльз И.
- https://www.topcoder.com/
- https://www.learneroo.com/subjects/8
- https://www.careercup.com/
- https://www.interviewbit.com/
- https://www.kalzumeus.com/2011/10/28/dont-call-yourself-a-programmer/
- https://careers.google.com/stories/apm-preparation-materials/
- https://www.criteriacorp.com/candidates/ccat-prep
- https://www.amazon.jobs/content/en/our-workplace/leadership-principles
- https://easyoffer.ru/
ООП
- Инкапсуляция (разделение доступа)
- Наследование
- Полиморфизм (полиморфные методы для каждого типа свой метод)
SOLID
- https://levelup.gitconnected.com/solid-principles-simplified-php-examples-based-dc6b4f8861f6
- https://web-creator.ru/articles/solid
- S - Принцип единственной ответственности (The Single Responsibility Principle)
- Следование принципу заключается обычно в декомпозиции сложных классов, которые делают сразу много вещей, на простые, отвественность которых очень специализирована.
- O - Принцип открытости/закрытости (The Open Closed Principle)
- Программные сущности (классы, модули, функции и т. п.) должны быть открыты для расширения, но закрыты для изменения
- L - Принцип подстановки Барбары Лисков (The Liskov Substitution Principle)
- При построении иерархий наследования создаваемые наследники должны корректно реализовывать поведение базового типа. Наследник класса дополняет, но не заменяет поведение базового класса. То есть в любом месте программы замена базового класса на класс‑наследник не должна вызывать проблем.
- I - Принцип разделения интерфейса (The Interface Segregation Principle)
- Заключается в создании интерфейсов, которые достаточно специфичны и требуют только необходимый минимум реализаций методов. Избыточные интерфейсы, напротив, могут требовать от реализующего класса создание большого количества методов, причём даже таких, которые не имеют смысла в контексте класса.
- D - Принцип инверсии зависимостей (The Dependency Inversion Principle)
- Следование принципу инверсии зависимостей «заставляет» реализовывать высокоуровневые компоненты без встраивания зависимостей от конкретных низкоуровневых классов, что, например, сильно упрощает замену используемых зависимостей как по бизнес‑требованиям, так и для целей тестирования. При этом зависимость формируется не от конкретной реализации, а от абстракции — реализуемого зависимостью интерфейса.
Паттерны проектирования
- https://designpatternsphp.readthedocs.io/ru/latest/README.html
- https://www.kobzarev.com/wp-content/uploads/books/php/PHPbook.pdf
- https://refactoring.guru/ru/design-patterns
- Порождающие паттерны
- Абстрактная фабрика
- Одиночка
- Прототип
- Строитель
- Фабричный метод
- Структурные паттерны
- Адаптер
- Декоратор
- Заместитель
- Компоновщик
- Мост
- Приспособленец
- Фасад
- Паттерны поведения
- Интерпретатор
- Итератор
- Команда
- Наблюдатель
- Посетитель
- Посредник
- Состояние
- Стратегия
- Хранитель
- Цепочка обязанностей
- Шаблонный метод
Чистая архитектура
Domain Driven Design
- Единый язык (Ubiquitous Language)
- Домены и субдомены
- Ubiquitous Language - общий язык с заказчиком
- Стратегическое моделирование - стратегия управления бизнесом
- Тактическое моделирование - итеративная разработка ПО
- Bounded Context - граница предметной области
- Context Map - как Bounded Context связан с другими
Паттерны микросервисов
- Паттерны декомпозиции на микросервисы
- Шаблон «Разбиение по бизнес-возможностям» (Decompose By Business Capability)
- Шаблон «Разбиение по поддоменам» (Decompose By Subdomain)
- Паттерны рефакторинга для перехода на микросервисы
- Шаблон «Душитель» (Strangler)
- Шаблон «Уровень защиты от повреждений» (Anti-Corruption Layer)
- Паттерны управления данными в микросервисной архитектуре
- Шаблон «База данных на сервис» (Database Per Service)
- Шаблон «API-композиция» (API Composition)
- Шаблон «Разделение команд и запросов» (Command Query Responsibility Segregation, CQRS)
- Шаблон «Поиск событий» (Event Sourcing)
- Шаблон «Сага» (Saga)
- Паттерны коммуникации микросервисов
- Шаблон «API-шлюз» (API Gateway)
- Шаблон «Бэкенды для фронтендов» (Backends for Frontends, BFF)
- Паттерны построения пользовательского интерфейса
- Шаблон «Сборка пользовательского интерфейса на стороне клиента» (Client-Side UI Composition)
- Шаблон «Сборка фрагментов страниц на стороне сервера» (Server-Side Page Fragment Composition)
- Паттерны обнаружения сервисов в микросервисной архитектуре
- Шаблон «Обнаружение сервисов на стороне клиента» (Client-Side Service Discovery)
- Шаблон «Обнаружение сервисов на стороне сервера» (Server-Side Service Discovery)
- Паттерны развертывания микросервисов
- Шаблон «Экземпляр сервиса на хост» (Service Instance Per Host)
- Шаблон «Сине-зеленое развертывание» (Blue-Green Deployment)
- Паттерны повышения отказоустойчивости
- Шаблон «Автоматический выключатель» (Circuit Breaker)
- Шаблон «Переборка» (Bulkhead)
- Паттерны мониторинга микросервисов
- Шаблон «Агрегация логов» (Log Aggregation)
- Шаблон «Распределенная трассировка» (Distributed Tracing)
- Шаблон «Проверки здоровья» (Health Check)
- Прочие паттерны проектирования микросервисов
- Шаблон «Посредник» («Посол», Ambassador)
- Шаблон «Коляска» («Прицеп», Sidecar)
- Шаблон «Тестирование контрактов, ориентированных на потребителя» (Consumer-Driven Contract Testing)
- Шаблон «Внешняя конфигурация» (External Configuration)
Дженерики
ACID
- Atomicity — Атомарность
- Consistency — Согласованность
- Isolation — Изолированность
- Durability — Долговечность
Уровни изоляции транзакций
- https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html
- https://www.postgresql.org/docs/current/transaction-iso.html
SELECT @@GLOBAL.transaction_isolation, @@GLOBAL.transaction_read_only; SELECT @@SESSION.transaction_isolation, @@SESSION.transaction_read_only;
Уровень изоляции | Черновое чтение | Невоспроизводимое чтение | Фантомное чтение | Блокировка чтения |
---|---|---|---|---|
READ UNCOMMITTED | Yes | Yes | Yes | No |
READ COMMITTED | No | Yes | Yes | No |
REPEATABLE READ | No | No | Yes | No |
SERIALIZABLE | No | No | No | Yes |
DROP TABLE IF EXISTS `money_transactions`; CREATE TABLE `money_transactions` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `user_from_id` bigint(20) unsigned DEFAULT NULL, `user_to_id` bigint(20) unsigned DEFAULT NULL, `volume` decimal(19,6) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; DROP TABLE IF EXISTS `money_accounts`; CREATE TABLE `money_accounts` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `user_id` bigint(20) unsigned DEFAULT NULL, `volume` decimal(19,6) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY (`user_id`) ) ENGINE=InnoDB; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), NULL, 1, 10000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), NULL, 2, 4300.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
READ UNCOMMITTED
Суть в том, что незакрепленные транзакции видны в другой открытой транзакции
SET @user_id = 1; SET @user_to_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
SET @user_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION; SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | 5 | 2024-02-12 14:48:29 | 1 | 2 | 3000.000000 | | 6 | 2024-02-12 14:48:29 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | 5 | 2024-02-12 14:48:29 | 1 | 2 | 3000.000000 | | 6 | 2024-02-12 14:48:29 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
READ COMMITTED
Суть в том, что если в первой транзакции был коммит - вы увидите из нее изменения, хотя находитесь в транзакции.
SET @user_id = 1; SET @user_to_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; START TRANSACTION; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; COMMIT;
SET @user_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; START TRANSACTION; SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | 7 | 2024-02-12 15:13:40 | 1 | 2 | 3000.000000 | | 8 | 2024-02-12 15:13:40 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 13:34:24 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 13:34:24 | NULL | 2 | 4300.000000 | | 7 | 2024-02-12 15:13:40 | 1 | 2 | 3000.000000 | | 8 | 2024-02-12 15:13:40 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
REPEATABLE READ
В MySQL этот уровень по-умолчанию. Суть в том, что возможно чтение фантомных строк - закрепленных другими транзакциями. Тест показал, что транзакции не изолированы
SET @user_id = 1; SET @user_to_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; START TRANSACTION; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; COMMIT;
SET @user_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; START TRANSACTION; SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 15:27:39 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 15:27:39 | NULL | 2 | 4300.000000 | | 3 | 2024-02-12 15:28:22 | 1 | 2 | 3000.000000 | | 4 | 2024-02-12 15:28:22 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
> SELECT * FROM `money_transactions`; +----+---------------------+--------------+------------+--------------+ | id | created_at | user_from_id | user_to_id | volume | +----+---------------------+--------------+------------+--------------+ | 1 | 2024-02-12 15:27:39 | NULL | 1 | 10000.000000 | | 2 | 2024-02-12 15:27:39 | NULL | 2 | 4300.000000 | | 3 | 2024-02-12 15:28:22 | 1 | 2 | 3000.000000 | | 4 | 2024-02-12 15:28:22 | 2 | 1 | -3000.000000 | +----+---------------------+--------------+------------+--------------+ 4 rows in set (0.00 sec) > SELECT * FROM `money_accounts`; +----+---------+-------------+ | id | user_id | volume | +----+---------+-------------+ | 1 | 1 | 7000.000000 | | 2 | 2 | 7300.000000 | +----+---------+-------------+ 2 rows in set (0.00 sec)
SERIALIZABLE
Суть в том, что вставка в левой сессии заблокируется, т.к. было чтение из правой сессии. Блокируется чтение - поэтому вы не сможете получить данные.
SET @user_id = 1; SET @user_to_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; START TRANSACTION; INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_id, @user_to_id, 3000.0); INSERT INTO `money_transactions` VALUES (DEFAULT, NOW(), @user_to_id, @user_id, -3000.0); INSERT INTO `money_accounts` SELECT NULL AS `id`, T.`user_to_id` AS `user_id`, SUM(T.`volume`) AS `volume` FROM `money_transactions` AS T GROUP BY T.`user_to_id` ON DUPLICATE KEY UPDATE `volume` = VALUES(`volume`); SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; COMMIT;
SET @user_id = 2; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE; START TRANSACTION; SELECT * FROM `money_transactions`; SELECT * FROM `money_accounts`; ROLLBACK;
Алгоритмы
- Не забываем про рекурсию
Сложность алгоритмов
PHP
- https://designpatternsphp.readthedocs.io/en/latest/README.html
- https://refactoring.guru/ru/design-patterns
- https://www.php.net/spl
- История изменений
- Типы данных:
- null
- Скалярные:
- bool
- int
- float
- string
- array
- object
- resource
- never
- void
- self, parent, static
- true, false
- null
- Магические методы:
- __construct(mixed ...$values = ""): void - конструктор, вызывается при new ClassName($param1, $param2, $param3)
- __destruct() - деструктор - вызывается при уничтожении объекта
- __call(string $name, array $arguments): mixed - вызывается при вызове метода с параметрами
- __callStatic(string $name, array $arguments): mixed - вызывается при вызове статического метода с параметрами
- __get(string $name): mixed - будет выполнен при чтении данных из недоступных (защищённых или приватных) или несуществующих свойств.
- __set(string $name, mixed $value): void - будет выполнен при записи данных в недоступные (защищённые или приватные) или несуществующие свойства.
- __isset(string $name): bool - будет выполнен при использовании isset() или empty() на недоступных (защищённых или приватных) или несуществующих свойствах.
- __unset(string $name): void - будет выполнен при вызове unset() на недоступном (защищённом или приватном) или несуществующем свойстве.
- __sleep(): array - Если метод определили, он выполняется перед сериализацией. Метод может очистить объект и должен вернуть массив с именами всех переменных этого объекта, которые должны быть сериализованы. Если метод ничего не возвращает, то сериализуется константа null и выдаётся предупреждение E_NOTICE.
- __wakeup(): void - восстановить соединения с базой данных, которые могли потеряться во время сериализации, и выполнить другие задачи повторной инициализации.
- __serialize(): array - Если метод определили, функция выполняется перед сериализацией. Метод должен создать и вернуть ассоциативный массив пар ключ и значение, которые представляют сериализованную форму объекта.
- __unserialize(array $data): void - Если метод определили, PHP передаст методу массив, который восстановил и вернул метод __serialize(). Затем, если нужно, метод восстанавливает свойства объекта из этого массива.
- __toString(): string - разрешает классу выбирать, как класс будет реагировать, когда с ним обращаются как со строкой.
- __invoke( ...$values): mixed - вызывается, когда скрипт пытается выполнить объект как функцию.
- __set_state(array $properties): object - Этот статический метод вызывается для тех классов, которые экспортируются функцией var_export().
- __clone(): void - После завершения клонирования, если метод __clone() определён, то будет вызван метод __clone() вновь созданного объекта для возможного изменения всех необходимых свойств.
- __debugInfo(): array - Этот метод вызывается функцией var_dump(), когда необходимо вывести список свойств объекта. Если этот метод не определили, выводится каждое свойство объекта c модификаторами public, protected и private
- Суперглобальные переменные
- $GLOBALS - Ссылается на переменные глобальной области видимости
- $_SERVER - это массив (array), содержащий такую информацию, как заголовки, пути и местоположения скриптов. Записи в этом массиве создаются веб-сервером, поэтому нет гарантии, что каждый веб-сервер будет предоставлять любую из этих переменных
- $_GET - Ассоциативный массив переменных, переданных скрипту через параметры URL (известные также как строка запроса).
- $_POST - Ассоциативный массив данных, переданных скрипту через HTTP методом POST при использовании application/x-www-form-urlencoded или multipart/form-data в заголовке Content-Type запроса HTTP.
- $_FILES - Ассоциативный массив элементов, загруженных в текущий скрипт через метод HTTP POST.
- $_COOKIE - Ассоциативный массив значений, переданных скрипту через HTTP Cookies.
- $_SESSION - Ассоциативный массив, содержащий переменные сессии, которые доступны для текущего скрипта.
- $_REQUEST - Ассоциативный массив, который по умолчанию содержит данные переменных $_GET, $_POST и $_COOKIE.
- $_ENV - Ассоциативный массив значений, переданных скрипту через переменные окружения.
JavaScript
- 16 САМЫХ ПОПУЛЯРНЫХ вопросов по JavaScript на собеседованиях
- СОБЕСЕДОВАНИЕ FRONTEND ЗП 220к JS, TS задачи
- var, let, const
- var - объявляет или глобально или в теле функции
- let - объявляет в блоке кода {}
- const - как let, только нельзя менять ссылку на объект
- Блокировка изменения объекта
let obj = {}; Object.defineProperty(obj, 'name', { value: 'John', writable: false,// можно ли изменять enumerable: true,// можно ли перечислять в циклах configurable: false// можно ли изменять другие дескрипторы, удалять или менять тип свойства });
Object.preventExtensions(obj); //запретит добавлять новые свойства Object.seal(obj);//запретит добавлять, удалять, но позволяет менять изменять свойства Object.freeze(obj);// замораживает объект
- Клонирование объектов
- Поверхностная копия Shallow
- Object.assign({}, objectToCopy)
- {...objectToCopy} - спред оператор
- Глубока Deep
- JSON.parse(JSON.stringify(objectToCopy))
- structuredClone(objectToCopy);
- https://lodash.com/docs/4.17.15#cloneDeep _.cloneDeep(objectToCopy);
- Поверхностная копия Shallow
function deepClone(value) { if (typeof value !== 'object' || value === null) { return value; } if (Array.isArray(value)) { return value.map((item) => deepClone(item)); } return Object.fromEntries(Object.entries(value).map(([key, value]) => [key, deepClone(value)])); }
- Типы данных
- Number - целое или плав.точка или NaN typeof(value) === 'number'
- String - "Test", 'Test', `Test, ${test}` [1] typeof(value) === 'string'
- Boolean - true/false, typeof(value) === 'boolean'
- null - пустое значение, typeof(value) === 'object'
- undefined - неопределенное значение, typeof(value) === 'undefined'
- Symbol - уникальный тип данных, typeof(value) === 'symbol'
- BigInt - произвольная точность или через конструктор или 12345n, typeof(value) === 'bigint'
- Object - или через конструктор или {}, typeof(value) === 'object'
- Array - или через конструктор или [], typeof(value) === 'object', Array.isArray(value) === true
- Function - или прямое объявление или через анонимную typeof(value) === 'function'
- Date - new Date(), typeof(value) === 'object'
- RegExp - или через new RegExp('^[a-z]*$', flags) или /^[a-z]*$/flags
- Map - карта - new Map(), map.set(key, value), typeof(map) === 'object'
- Set - набор уникальных значений - new Set(array) или set.add(value), typeof(set) === 'object' set.has(val) -> O(1)
- WeakMap, WeakSet - Garbage Collector чистит значения, если исходные были удалены.
- Garbage Collector
- Mark(пометка недостижимых объектов) & Sweap(удаление)
- Function Declaration и Function Expression
- Function Declaration
console.log(factorial(5));// функция всплывает function factorial(n) { if (n <= 1) { return 1; } return n * factorial(n - 1); }
- Function Expression
const factorial = function factorial(n) { if (n <= 1) { return 1; } return n * factorial(n - 1); }; console.log(factorial(5));// функция не всплывает
- Function Generator
function* generatorFunction() { yield 1; yield 2; return 3; } const gen = generatorFunction(); console.log(gen.next());// {value: 1, done: false}
- Arrow Function
() => expression param => expression (param) => expression (param1, paramN) => expression () => { statements } param => { statements } (param1, paramN) => { statements }
this
- this - контекст, которым можно манипулировать. (Как работает this в javascript. Разберемся на примерах опираясь на официальную спецификацию)
- bind(thisArg, arg1, arg2, /* …, */ argN)
Привязка контекста к функции
let user = { firstName: "Вася", sayHi() { alert(`Привет, ${this.firstName}!`); } }; let sayHi = user.sayHi.bind(user); // (*) sayHi(); // Привет, Вася! setTimeout(sayHi, 1000); // Привет, Вася!
- call, apply - вызывает функцию с контекстом
func.call(context, arg1, arg2); // идентичен вызову func.apply(context, [arg1, arg2]);
- arguments
- у new Function() this - {} - пустой объект
- у ArrowFunction контекст берется из окружения, изменить его нельзя. arguments не передается
- у global - this глобальный объект
- у module - this undefined
dot нотация
У JavaScript есть 2 способа обращаться к свойствам объекта.
Через точку Obj.theProperty и через строчку Obj["theProperty"] - это идентично.
Функции объекта вызываются аналогично
Obj.theFunc(); Obj["theFunc"]();
modules
Позволяет разделить код на модули
export const name = "square"; export function draw(ctx, length, x, y, color) { ctx.fillStyle = color; ctx.fillRect(x, y, length, length); return { length, x, y, color }; }
и потом их импортировать
import { name, draw, reportArea, reportPerimeter } from "./modules/square.js";
экспорт можно прописать отдельной инструкцией
export { name, draw, reportArea, reportPerimeter };
модули можно хранить в *.mjs или *.js файлах
Сравнение
Также есть
Замыкание(Closure)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
Это функция, которая сохраняет доступ к переменным из своего внешнего окружения, даже после того как это окружение перестало существовать.
Я никогда не понимал почему это назвали замыканием. Я бы назвал - ближайшее окружение.
Асинхронность
Метод "в лоб"
function doSomethingAsync(callback) { setTimeout(() => { callback(); }); } doSomethingAsync(() => { console.log('async code'); });
- Promise
- Pending
- Fulfilled
- Rejected
- Promise.all() - принимает массив, возвращает промис с выполненными промисами или одну ошибку
- Promise.allSettled() - принимает массив, возвращает промис с результатами
- Promise.any() - принимает массив, возвращает результат любого успешного промиса или ошибку в случае безуспешного результата
- Promise.race() - принимает массив, возвращает результат первого промиса или ошибку
- Promise.reject()
- Promise.resolve()
- Promise.try()
- Promise.withResolvers()
function checkMail() { return new Promise((resolve, reject) => { if (Math.random() > 0.5) { resolve('Mail has arrived'); } else { reject(new Error('Failed to arrive')); } }); } checkMail() .then((mail) => { console.log(mail); }) .catch((err) => { console.error(err); }) .finally(() => { console.log('Experiment completed'); });
- Async Await
function resolveAfter2Seconds() { return new Promise((resolve, reject) => { setTimeout(() => { resolve('resolved'); }, 2000); }); } async function asyncCall() { console.log('calling'); const result = await resolveAfter2Seconds().catch((value) => {console.error(value);}).finally(() => {console.log('finally');}); console.log(result); // Expected output: "resolved" } asyncCall();
- Observable RxJS [7]
function checkMail() { return new Observable((subscriber: Subscriber<string | null>) => { if (Math.random() > 0.5) { subscriber.next('next'); } else { subscriber.complete(); // subscriber.error(new Error('12345')); // subscriber.unsubscribe(); } }); } checkMail() .subscribe({ next: (results: string | null): void => { console.log(results); }, error: (err) => console.error('something wrong occurred: ', err), complete: () => { console.log('complete'); }, });
Prototype
Прототипы позволяют организовать прототипное наследование
function Person(name) { this.name = name; } Person.prototype.greet = function() { console.log(`Hello, my name is ${this.name}!`); } const john = new Person('John'); john.greet(); // Hello, my name is John
Вытащить прототип объекта (getPrototypeOf или __proto__(устар))
const obj = {}; console.log(obj.toString());// [object Object] console.log(Object.getPrototypeOf(obj) === Object.prototype);// true console.log(Object.getPrototypeOf(obj.prototype) === null);// true
Установить прототип
const proto = { greet: function() { console.log('Hello!'); } }; const obj = {}; Object.setPrototypeOf(obj, proto); obj.greet(); // Hello!
Метод Object.hasOwn проверяет наличие собственного свойства у объекта.
Метод Object.hasOwnProperty проверяет, является ли свойство собственным свойством объекта. Он не учитывает свойства, унаследованные по цепочке прототипов.
Debounce, throttle, curry
function debounce(func, wait) { let timeout; return function(...args) { const context = this; clearTimeout(timeout); timeout = setTimeout(() => func.apply(context, args), wait); }; } // Пример использования window.addEventListener('resize', debounce(() => { console.log('Resize event'); }, 200));
function throttle(func, limit) { let lastFunc; let lastRan; return function(...args) { const context = this; if (!lastRan) { func.apply(context, args); lastRan = Date.now(); } else { clearTimeout(lastFunc); lastFunc = setTimeout(function() { if ((Date.now() - lastRan) >= limit) { func.apply(context, args); lastRan = Date.now(); } }, limit - (Date.now() - lastRan)); } }; } // Пример использования window.addEventListener('scroll', throttle(() => { console.log('Scroll event'); }, 200));
function curry(func) { return function curried(...args) { if (args.length >= func.length) { return func.apply(this, args); } else { return function(...nextArgs) { return curried.apply(this, args.concat(nextArgs)); }; } }; } // Пример использования function sum(a, b, c) { return a + b + c; } const curriedSum = curry(sum); console.log(curriedSum(1)(2)(3)); // 6 console.log(curriedSum(1, 2)(3)); // 6 console.log(curriedSum(1, 2, 3)); // 6
function partial(func, ...fixedArgs) { return function(...args) { return func.apply(this, fixedArgs.concat(args)); }; } const add = (a, b, c) => a + b + c; const add5 = partial(add, 5); console.log(add5(10, 15)); // 30
Event Loop
- Стек вызовов (Call stack) - структура данных, где хранятся текущие выполняющиеся функции. Когда функция вызывается, она добавляется в стек вызовов, когда её выполнение завершается, она удаляется из стека вызовов.
- Web API - браузер предоставляет различные API для создания веб-приложений (DOM API, Storage API, XMLHttpRequest)
- Очередь тасок (Task queue) - очередь, куда попадают задачи от Web API
- Очередь микротасок (Microtask queue) - очередь, куда попадают задачи от промисов, MutationObserver, IntersectionObserver, queueMicrotask(),
Алгоритм работы
- Выполнить все синхронные задачи, задачи с Web API отдать на выполнение браузеру.
- Выполнить все задачи из очереди микротасок (выполняются, пока очередь не опустеет)
- Выполнить одну макротаску из очереди макротасок
- Произвести рендеринг
- Начать с 1 шага
const myFn = async() => { console.log("1");// -> Call stack setTimeout(() => console.log("6"));// -> Task queue Promise.resolve().then(() => console.log("4"));// -> Microtask queue console.log("2");// -> Call stack await Promise.resolve();// -> Microtask queue console.log("5");// -> Microtask queue } myFn(); console.log("3");// -> Call stack // Call stack // Microtask queue // Task queue 1 2 3 4 5 6
- requestAnimationFrame
- requestIdleCallback
TypeScript
Angular
Python
Golang
- Собеседование Golang разработчика (теоретические вопросы), Часть I
- Собеседование Golang разработчика (теоретические вопросы), Часть II. Что там с конкурентностью?
SQL
Linux Boot
Поведенческие вопросы
Решение задач
- https://www.leetcode.com/
- https://www.hackerrank.com/
- https://www.interviewbit.com/
- https://www.careercup.com/
- https://www.algoexpert.io/
- https://www.educative.io/
- https://www.pluralsight.com/
- https://www.learneroo.com/
- https://coderbyte.com/
Дизайн систем
Схема ответа
- Сбор функциональных требований (что должно быть)
- Сбор нефункциональных требований (как оно должно быть) + некая вводная
- Расчет ресурсов RPS write, RPS read, потоки данных, объемы хранилищ
- Проектирование API (основные методы, схема)
- Проектирование архитектуры (сервисы, блоки, базы данных, очереди, кэши)
- Проектирование БД (таблицы в бд сервисов)
- Оценка отказоустойчивости и масштабируемости системы
- Расчет железа и сети
- Сценарии отказов
- Логгирование
- Мониторинги
Ссылки
- https://habr.com/ru/companies/yandex/articles/564132/
- https://www.educative.io/courses/grokking-modern-system-design-interview-for-engineers-managers
- https://github.com/donnemartin/system-design-primer
- https://docs.google.com/document/d/1w3qb6SS1Hycyce5Fg5mVMdzkGYXTRskSf57IoD98ZQw/edit
- https://www.hiredintech.com/app#system-design
- Educative - https://www.educative.io/path/scalability-system-design
- YouTube Playlist - https://www.youtube.com/playlist?list=PLMCXHnjXnTnvo6alSjVkgxV-VH6EPyvoX
Время отклика систем
Latency Comparison Numbers -------------------------- L1 cache reference 0.5 ns Branch mispredict 5 ns L2 cache reference 7 ns 14x L1 cache Mutex lock/unlock 25 ns Main memory reference 100 ns 20x L2 cache, 200x L1 cache Compress 1K bytes with Zippy 10,000 ns 10 us Send 1 KB bytes over 1 Gbps network 10,000 ns 10 us Read 4 KB randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD Read 1 MB sequentially from memory 250,000 ns 250 us Round trip within same datacenter 500,000 ns 500 us Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory HDD seek 10,000,000 ns 10,000 us 10 ms 20x datacenter roundtrip Read 1 MB sequentially from 1 Gbps 10,000,000 ns 10,000 us 10 ms 40x memory, 10X SSD Read 1 MB sequentially from HDD 30,000,000 ns 30,000 us 30 ms 120x memory, 30X SSD Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms Notes ----- 1 ns = 10^-9 seconds 1 us = 10^-6 seconds = 1,000 ns 1 ms = 10^-3 seconds = 1,000 us = 1,000,000 ns
- https://ping-admin.ru/free_ping/
- До МСК
- Европа < 50
- До Урала < 50
- Владивосток 100
- США-Канада 150-250
- Южная Америка 200-300
- Азия 200-300
- Австралия 300
Расположение датацентров в мире
Не функциональные характеристики систем
Availability / Доступность
Доступность % | Недоступность в год | Недоступность в месяц | Недоступность в неделю |
---|---|---|---|
90% (1 девяток) | 36.5 дней | 72 часов | 16.8 часов |
99% (2 девяток) | 3.65 дней | 7.20 часов | 1.68 часов |
99.5% (2 девяток) | 1.83 дней | 3.60 часов | 50.4 минут |
99.9% (3 девяток) | 8.76 часов | 43.8 минут | 10.1 минут |
99.99% (4 девяток) | 52.56 минут | 4.32 минут | 1.01 минут |
99.999% (5 девяток) | 5.26 минут | 25.9 секунд | 6.05 секунд |
99.9999% (6 девяток) | 31.5 секунд | 2.59 секунд | 0.605 секунд |
99.99999% (7 девяток) | 3.15 секунд | 0.259 секунд | 0.0605 секунд |
Reliability / Надежность
Среднее время между отказами (MTBF)
Среднее время отказа (MTTF)
Среднее время восстановления(MTTR)
Scalability / Масштабируемость
- Вертикальное масштабирование - увеличение мощности узлов (CPU(Frequency, # of cores), MEM(Volume, Frequency), HDD->SSD->NVMe)
- Горизонтальное масштабирование - увеличение количества узлов
Maintainability / Поддерживаемость
- Главный параметр - MTTR
- Легкость кода и прозрачность разработки
Fault Tolerance / Устойчивость к сбоям
- Отказоустойчивость - способность системы обслуживать запросы даже при отказе ее частей.
- Можно достичь шардингом и репликацией
Сколько нужно серверов?
Блоки систем
- DNS
- Load balancers - Балансировщики
- Databases - Базы данных
- KV Storage - Хранилища Ключ Значение
- CDN - Сеть доставки контента
- Sequencer - генератор идентификаторов
- Мониторинг
- Распределенный кэш
- Распределенная очередь сообщений
- Издатель-подписчик
- Ограничитель нагрузки
- Файловое хранилище
- Распределенный поиск
- Распределенное логгирование
- Распределенное задачи по расписанию
- Шардированные счетчики.