Programming Flashcards
O нотація, оцінка складності алгоритму
O(1) — (складність порядку 1) одна операція для всіх можливих вхідних даних. Алгоритм виконується за константний час. Якщо операцій декілька, все одно вважається O(1), оскільки нас цікавить співвідношення до вхідних даних.
O(n) — (складність порядку n) лінійний алгоритм. Наприклад, пройтися по масиву та підрахувати суму елементів.
O(log n) — якщо масив відсортований, можна застосувати алгоритм бінарного пошуку та кожного разу відкидати половину елементів, які нам не підходять. У цьому випадку не потрібно перебирати кожен елемент, і час виконання буде меншим.
O(n^2) — (складність порядку n у квадраті) у алгоритмів із вкладеним циклом.
O(n * log n) — коли ми замінили два вкладених проходи на бінарний пошук.
Поток vs процес
Процес — це окремий екземпляр програми, якому виділені ресурси системи. Кожен процес ізольований і не може безпосередньо отримати доступ до змінних іншого. У Node.js можна використовувати модуль child_process для запуску паралельних процесів та обміну повідомленнями.
Потоки — виконуються паралельно всередині процесу, і потоки одного процесу можуть працювати з однією областю пам’яті через SharedArrayBuffer. Створення нового потоку відбувається швидше, ніж створення нового процесу. У Node.js можна використовувати worker_threads для запуску завдань у новому потоці.
Stack vs queue
Stack - first in last out. Queue - first in first out.
Основні принципи ООП
Абстракція - відображення сутностей реального світу у вигляді об’єктів із прихованням деталей їхньої реалізації.
Наслідування — клас може мати класи-нащадки, які можуть розширювати й змінювати його поведінку.
Поліморфізм — класи можуть мати однаковий інтерфейс, але різну поведінку.
Інкапсуляція — приховування реалізації. У класу може бути публічний і приватний інтерфейс.
Generic, узагальнений тип
Дозволяє зарезервувати місце для типу, який буде вказано пізніше при виклику функції, роботі з класами або типами.
Паттерни проектування, які ти використовуєш у своїх проектах
Singleton — реалізується просто завдяки вбудованому механізму кешування модулів у Node.js. Після першого підключення, модуль стає доступним як той самий екземпляр по всьому проекту.
Adapter — створює простіший інтерфейс для взаємодії з іншою бібліотекою, дозволяючи використовувати значення за замовчуванням.
Decorator — додає додаткову функціональність до методу або класу динамічно, не змінюючи їхньої базової структури.
Factory — забезпечує простий інтерфейс для створення об’єктів, абстрагуючи складності інстанціації.
Observer — дає змогу отримувати сповіщення про зміну стану, що дозволяє налаштовувати реакції на ці зміни.
Dependency Injection — у цьому паттерні залежність передається як аргумент. Це робить модуль легшим для тестування, бо ініціалізація залежності відбувається ззовні, знімаючи відповідальність за це з самого модуля. У результаті можна уникнути синглтонів, просто ініціалізуючи модуль один раз і передаючи його далі по ланцюжку.
Mediator — дозволяє об’єктам взаємодіяти через посередника, без прямої залежності один від одного.
Facade — єдиний інтерфейс до множини інших інтерфейсів, спрощуючи доступ до складних підсистем.
Принцип SOLID
Принцип єдиного обов’язку (Single Responsibility Principle) — об’єкт має мати пов’язаний набір функціоналу з єдиною відповідальністю.
Принцип відкритості/закритості (Open/Closed Principle) — функціонал повинен бути відкритий для розширення, але закритий для зміни. Код має бути гнучким і легко масштабованим.
Принцип підстановки Лісков (Liskov Substitution Principle) — нащадки і батьківські класи мають бути взаємозамінними.
Принцип розділення інтерфейсу (Interface Segregation Principle) — кілька спеціалізованих інтерфейсів кращі, ніж один універсальний. Погано, коли ми створили інтерфейс, а під час його реалізації робимо методи-заглушки.
Принцип інверсії залежностей (Dependency Inversion Principle) — код має залежати від абстракцій, а не від деталей. Наприклад, у JS можна створити клас MessageQueue, який, не прив’язуючись до конкретного клієнта чи протоколу, буде відправляти та отримувати повідомлення. Це дозволить легко змінити реалізацію черг при потребі.
Принцип KISS
KISS — keep it simple, stupid. Хороший код легко читається, його просто зрозуміти, він використовує загальноприйняті впізнавані підходи.
Принцип DRY
DRY — don’t repeat yourself. Потрібно уникати копіювання коду та ситуацій, коли його потрібно змінювати в декількох місцях одночасно. Краще винести код в окремий модуль або додати йому універсальності.
Принцип YAGNI
YAGNI — You Ain’t Gonna Need It. Не варто писати код, який не потрібен зараз, але може знадобитися в майбутньому. Кожен написаний код має бути добре протестований і задокументований, інакше виникнуть проблеми з його підтримкою. Якщо ж ми робимо це для непотрібного функціоналу, то даремно витрачаємо час.
IoC
Інверсія керування - це принцип програмування, при якому об’єкт не самостійно керує своїми залежностями, а отримує їх ззовні (Dependancy Injection).
Рекурсия, trampoline
Функція, яка викликає саму себе.
У JS, щоб уникнути stack overflow, можна реалізувати trampoline. Для цього потрібно створити функцію, яка прийматиме рекурсивну функцію і виконуватиме її в циклі while, поки результатом є функція, а не значення. Сама рекурсивна функція повинна обгорнути рекурсивний виклик в анонімну функцію.
const trampoline = fn => {
while (typeof fn === ‘function’) {
fn = fn();
}
return fn;
};
Яке буває масштабування?
Вертикальне масштабування — нарощування потужностей. Збільшуємо розмір інстансу.
Горизонтальне масштабування — запуск більшої кількості серверів або екземплярів застосунку. Додаємо збоку більше машин.
Що таке TCP?
Transport Control Protocol (TCP) — це протокол передачі даних у мережі. Працює на 4-му транспортному рівні. Підтримує попереднє встановлення з’єднання, повідомляє про результати доставки, здійснює повторний запит у разі втрати даних і усуває дублювання. Тобто TCP гарантує цілісність передачі даних.
Що таке UDP?
UDP (User Datagram Protocol) — це швидкий, ненадійний протокол передачі даних без підтвердження доставки та перевірки порядку пакетів. Використовується для застосунків у реальному часі, де затримка важливіша за надійність, як у стрімінгу й іграх.