Работа мечты: различия между версиями

Материал из Artem Aleksashkin's Wiki
Перейти к навигации Перейти к поиску
 
(не показано 5 промежуточных версий этого же участника)
Строка 95: Строка 95:
* https://www.amazon.jobs/content/en/our-workplace/leadership-principles
* https://www.amazon.jobs/content/en/our-workplace/leadership-principles
* https://easyoffer.ru/
* https://easyoffer.ru/
== Алгоритмы ==
* [[Алгоритмы]]


== ООП ==
== ООП ==
Строка 551: Строка 555:
== PHP ==
== PHP ==


* https://designpatternsphp.readthedocs.io/en/latest/README.html
* [[PHP]]
* https://refactoring.guru/ru/design-patterns
* https://www.php.net/spl
* История изменений
** [https://www.php.net/releases/8.0/ru.php 8.0]
** [https://www.php.net/releases/8.1/ru.php 8.1]
** [https://www.php.net/releases/8.2/ru.php 8.2]
** [https://www.php.net/releases/8.3/ru.php 8.3]
* Типы данных:
** null
*** Скалярные:
*** bool
*** int
*** float
*** string
** array
** object
** resource
** never
** void
** self, parent, static
** true, false
* Магические методы:
** '''__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 ==
== JavaScript ==


* [https://www.youtube.com/watch?v=3kLS5UPvfss 16 САМЫХ ПОПУЛЯРНЫХ вопросов по JavaScript на собеседованиях]
* [[JavaScript]]
* [https://www.youtube.com/watch?v=p4PmANxsckA СОБЕСЕДОВАНИЕ FRONTEND ЗП 220к JS, TS задачи]
* var, let, const
** var - объявляет или глобально или в теле функции
** let - объявляет в блоке кода {}
** const - как let, только нельзя менять ссылку на объект
* Блокировка изменения объекта
<pre>
let obj = {};
Object.defineProperty(obj, 'name', {
  value: 'John',
  writable: false,// можно ли изменять
  enumerable: true,// можно ли перечислять в циклах
  configurable: false// можно ли изменять другие дескрипторы, удалять или менять тип свойства
});
</pre>
<pre>
Object.preventExtensions(obj); //запретит добавлять новые свойства
Object.seal(obj);//запретит добавлять, удалять, но позволяет менять изменять свойства
Object.freeze(obj);// замораживает объект
</pre>
* Клонирование объектов
** Поверхностная копия Shallow
*** Object.assign({}, objectToCopy)
*** {...objectToCopy} - спред оператор
** Глубока Deep
*** JSON.parse(JSON.stringify(objectToCopy))
*** structuredClone(objectToCopy);
*** https://lodash.com/docs/4.17.15#cloneDeep _.cloneDeep(objectToCopy);
<pre>
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)]));
}
</pre>
* Типы данных
** Number - целое или плав.точка или NaN typeof(value) === 'number'
** String - "Test", 'Test', `Test, ${test}` [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals] 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
<pre>
console.log(factorial(5));// функция всплывает
 
function factorial(n) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}
</pre>
 
** Function Expression
<pre>
const factorial = function factorial(n) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
};
 
console.log(factorial(5));// функция не всплывает
</pre>
* Function Generator
[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*]
<pre>
function* generatorFunction() {
    yield 1;
    yield 2;
    return 3;
}
 
const gen = generatorFunction();
console.log(gen.next());// {value: 1, done: false}
</pre>
* Arrow Function
<pre>
() => expression
param => expression
(param) => expression
(param1, paramN) => expression
() => {
  statements
}
param => {
  statements
}
(param1, paramN) => {
  statements
}
</pre>
 
== this ==
* this - контекст, которым можно манипулировать. ([https://www.youtube.com/live/4tg4qokVS9o Как работает this в javascript. Разберемся на примерах опираясь на официальную спецификацию])
** bind(thisArg, arg1, arg2, /* …, */ argN)
Привязка контекста к функции
<pre>
let user = {
  firstName: "Вася",
  sayHi() {
    alert(`Привет, ${this.firstName}!`);
  }
};
 
let sayHi = user.sayHi.bind(user); // (*)
 
sayHi(); // Привет, Вася!
 
setTimeout(sayHi, 1000); // Привет, Вася!
</pre>
** call, apply - вызывает функцию с контекстом
<pre>
func.call(context, arg1, arg2);
// идентичен вызову
func.apply(context, [arg1, arg2]);
</pre>
** arguments
** у new Function() this - {} - пустой объект
** у ArrowFunction контекст берется из окружения, изменить его нельзя. arguments не передается
** у global - this глобальный объект
** у module - this undefined
 
== dot нотация ==
 
У JavaScript есть 2 способа обращаться к свойствам объекта.
 
Через точку Obj.theProperty и через строчку Obj["theProperty"] - это идентично.
 
Функции объекта вызываются аналогично
 
Obj.theFunc();
Obj["theFunc"]();
 
== modules ==
 
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
 
Позволяет разделить код на модули
 
<pre>
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 };
}
</pre>
 
и потом их импортировать
 
<pre>
import { name, draw, reportArea, reportPerimeter } from "./modules/square.js";
</pre>
 
экспорт можно прописать отдельной инструкцией
<pre>
export { name, draw, reportArea, reportPerimeter };
</pre>
 
модули можно хранить в *.mjs или *.js файлах
 
== Сравнение ==
 
<gallery>
File:standartnoe-uslovie-IF.png|Условие IF
File:netochnoe-sravnenie-v-Javascript-.png|Неточное сравнение
File:tochnoe-sravnenie-v-Javascript-.png|Точное сравнение
</gallery>
 
Также есть
 
* Object.is() [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is]
* Number.isNaN() [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN]
* Array.isArray() [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray]
 
== Замыкание(Closure) ==
 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
 
Это функция, которая сохраняет доступ к переменным из своего внешнего окружения, даже после того как это окружение перестало существовать.
 
Я никогда не понимал почему это назвали замыканием. Я бы назвал - ближайшее окружение.
 
== Асинхронность ==
 
[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise]
 
Метод "в лоб"
<pre>
function doSomethingAsync(callback) {
    setTimeout(() => {
        callback();
    });
}
doSomethingAsync(() => {
    console.log('async code');
});
</pre>
 
* Promise
** Pending
** Fulfilled
** Rejected
 
* Promise.all() - принимает массив, возвращает промис с выполненными промисами или одну ошибку
* Promise.allSettled()  - принимает массив, возвращает промис с результатами
* Promise.any() - принимает массив, возвращает результат любого успешного промиса или ошибку в случае безуспешного результата
* Promise.race() - принимает массив, возвращает результат первого промиса или ошибку
* Promise.reject()
* Promise.resolve()
* Promise.try()
* Promise.withResolvers()
 
<pre>
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');
  });
 
</pre>
 
* Async Await
 
<pre>
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();
</pre>
 
* Observable RxJS [https://rxjs.dev/guide/observable]
<pre>
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');
        },
      });
</pre>
 
== Prototype ==
 
Прототипы позволяют организовать прототипное наследование
 
<pre>
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
</pre>
 
Вытащить прототип объекта (getPrototypeOf или __proto__(устар))
 
<pre>
const obj = {};
console.log(obj.toString());// [object Object]
 
console.log(Object.getPrototypeOf(obj) === Object.prototype);// true
console.log(Object.getPrototypeOf(obj.prototype) === null);// true
</pre>
 
Установить прототип
<pre>
const proto = { greet: function() { console.log('Hello!'); } };
const obj = {};
Object.setPrototypeOf(obj, proto);
obj.greet(); // Hello!
</pre>
 
[[File:js-prototype.png|thumb|none]]
 
Метод Object.hasOwn проверяет наличие собственного свойства у объекта.
 
Метод Object.hasOwnProperty проверяет, является ли свойство собственным свойством объекта. Он не учитывает свойства, унаследованные по цепочке прототипов.
 
== Debounce, throttle, curry ==
<pre>
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));
</pre>
 
<pre>
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));
</pre>
 
<pre>
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
</pre>
 
<pre>
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
</pre>
 
== Event Loop ==
 
* Стек вызовов (Call stack) - структура данных, где хранятся текущие выполняющиеся функции. Когда функция вызывается, она добавляется в стек вызовов, когда её выполнение завершается, она удаляется из стека вызовов.
* Web API - браузер предоставляет различные API для создания веб-приложений (DOM API, Storage API, XMLHttpRequest)
* Очередь тасок (Task queue) - очередь, куда попадают задачи от Web API
* Очередь микротасок (Microtask queue) - очередь, куда попадают задачи от промисов, MutationObserver, IntersectionObserver, queueMicrotask(),
 
Алгоритм работы
 
* Выполнить все синхронные задачи, задачи с Web API отдать на выполнение браузеру.
* Выполнить все задачи из очереди микротасок (выполняются, пока очередь не опустеет)
* Выполнить одну макротаску из очереди макротасок
* Произвести рендеринг
* Начать с 1 шага
 
<pre>
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
</pre>
 
* requestAnimationFrame
* requestIdleCallback


== TypeScript ==
== TypeScript ==
Строка 1083: Строка 570:
== Golang ==
== Golang ==


* [[Golang]]
* [https://habr.com/ru/articles/654569/ Собеседование Golang разработчика (теоретические вопросы), Часть I]
* [https://habr.com/ru/articles/654569/ Собеседование Golang разработчика (теоретические вопросы), Часть I]
** [https://habr.com/ru/companies/nixys/articles/492056/ 4 примера iota-перечислений]
** [https://habr.com/ru/companies/nixys/articles/492056/ 4 примера iota-перечислений]

Текущая версия от 21:12, 8 ноября 2024

  • Facebook
  • Amazon
  • Apple
  • Netflix
  • Google
  • Microsoft

Мотивация

Penguin-Falls-Over-Rock.gif

Характер + воспитание + обстоятельства = воля + мораль + закалка
  • Отрицание
  • Гнев
  • Торг
  • Депрессия
  • Принятие

Dream.jpeg

Nu-davay.jpg

Steps-motivation.jpg

Один работник заходит к хозяину и спрашивает:
– А почему ты платишь мне всего рубль в неделю, в то время как Елисею – пятнадцать? Хозяин смотрит в окно и говорит:
– Слышу, кто-то едет. Нам сена на зиму нужно купить. Выйди-ка, посмотри, не сено ли везут.

Вышел работник.
Зашел и говорит:
– Правда, сено.
– А не знаешь, откуда? Может, с Лукьяновских лугов?
– Не знаю.
– Так сходи и спроси.
Пошел тот.
Снова входит:
– Точно, с Лукьяновских.
– А сено какого укоса – первого или второго?
– Не знаю.
– Так сходи, узнай!
Вышел работник.
Возвращается:
– Хозяин! Первого укоса!
– А не знаешь, почем?
– Не знаю.
– Так сходи, узнай.
Сходил.
Вернулся и говорит:
– Хозяин! По двадцать рублей.
– А дешевле не дают?
– Не знаю.
В этот момент входит Елисей и говорит:
– Хозяин! Мимо везли сено с Лукьяновских лугов первого укоса. Просили по 20 рублей. Сторговались по 17 за воз. Я их загнал во двор, сейчас разгружают.
Хозяин поворачивается к первому:
– Теперь ты понял, почему тебе платят 1 рубль, а Елисею – 15?

Evg-sanya.jpg

Full-stack-developer.jpg

Cat-developer-home.jpg

90ie.jpg

Interview-vs-job.jpg

Compensations

Jobs Websites

Подготовка

Алгоритмы

ООП

  • Инкапсуляция (разделение доступа)
  • Наследование
  • Полиморфизм (полиморфные методы для каждого типа свой метод)

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)
    • Следование принципу инверсии зависимостей «заставляет» реализовывать высокоуровневые компоненты без встраивания зависимостей от конкретных низкоуровневых классов, что, например, сильно упрощает замену используемых зависимостей как по бизнес‑требованиям, так и для целей тестирования. При этом зависимость формируется не от конкретной реализации, а от абстракции — реализуемого зависимостью интерфейса.

Паттерны проектирования

  • Порождающие паттерны
    • Абстрактная фабрика
    • Одиночка
    • Прототип
    • Строитель
    • Фабричный метод
  • Структурные паттерны
    • Адаптер
    • Декоратор
    • Заместитель
    • Компоновщик
    • Мост
    • Приспособленец
    • Фасад
  • Паттерны поведения
    • Интерпретатор
    • Итератор
    • Команда
    • Наблюдатель
    • Посетитель
    • Посредник
    • Состояние
    • Стратегия
    • Хранитель
    • Цепочка обязанностей
    • Шаблонный метод

Чистая архитектура

Clean-architecture.png

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 — Долговечность

Уровни изоляции транзакций

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

JavaScript

TypeScript

Angular

Python

Golang

SQL

Linux Boot

Поведенческие вопросы

Решение задач

Дизайн систем

Схема ответа

  • Сбор функциональных требований (что должно быть)
  • Сбор нефункциональных требований (как оно должно быть) + некая вводная
  • Расчет ресурсов RPS write, RPS read, потоки данных, объемы хранилищ
  • Проектирование API (основные методы, схема)
  • Проектирование архитектуры (сервисы, блоки, базы данных, очереди, кэши)
  • Проектирование БД (таблицы в бд сервисов)
  • Оценка отказоустойчивости и масштабируемости системы
  • Расчет железа и сети
  • Сценарии отказов
  • Логгирование
  • Мониторинги

Ссылки

Время отклика систем

Latency.png

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 - генератор идентификаторов
  • Мониторинг
  • Распределенный кэш
  • Распределенная очередь сообщений
  • Издатель-подписчик
  • Ограничитель нагрузки
  • Файловое хранилище
  • Распределенный поиск
  • Распределенное логгирование
  • Распределенное задачи по расписанию
  • Шардированные счетчики.

Mock интервью

Interview tools

Демотиваторы

Qs-vs-real.png

Nizkoopl-programmist.jpg

Chatgpt-meme.jpeg

Nothing-to-eat.jpg

Suk-sidish.gif

Moskvich-bez-raboty.jpg

Digital-zavod.jpg

Pravki-po-makety.gif

Son-of-owner.jpg

Eboshit.jpeg