Вы находитесь на странице: 1из 110

ACID

требования к транзакционной системе (например, к СУБД), обеспечивающие наиболее


надёжную и предсказуемую её работу

Atomicity — Атомарность
Атомарность гарантирует, что никакая транзакция не будет зафиксирована в системе
частично. Будут либо выполнены все её подоперации, либо не выполнено ни одной.
Поскольку на практике невозможно одновременно и атомарно выполнить всю
последовательность операций внутри транзакции, вводится понятие «отката»
(rollback): если транзакцию не удаётся полностью завершить, результаты всех её до
сих пор произведённых действий будут отменены и система вернётся во «внешне
исходное» состояние — со стороны будет казаться,взсчто транзакции и не было.

Consistency — Согласованность
Транзакция, достигающая своего нормального завершения (EOT — end of transaction,
завершение транзакции) и, тем самым, фиксирующая свои результаты, сохраняет
согласованность базы данных. Другими словами, каждая успешная транзакция по
определению фиксирует только допустимые результаты. Это условие является
необходимым для поддержки четвёртого свойства.

Isolation — Изолированность
Во время выполнения транзакции параллельные транзакции не должны оказывать
влияния на её результат.

Durability — Стойкость
Независимо от проблем на нижних уровнях (к примеру, обесточивание системы или
сбои в оборудовании) изменения, сделанные успешно завершённой транзакцией,
должны остаться сохранёнными после возвращения системы в работу. Другими
словами, если пользователь получил подтверждение от системы, что транзакция
выполнена, он может быть уверен, что сделанные им изменения не будут отменены
из-за какого-либо сбоя.

Проблемы параллельного доступа с использованием


транзакций

lost update Потерянное обновление


Ситуация, когда при одновременном изменении одного блока данных разными
транзакциями одно из изменений теряется.

dirty read «Грязное» чтение


Чтение данных, добавленных или изменённых транзакцией, которая впоследствии не
подтвердится (откатится).
non-repeatable read Неповторяющееся чтение
Ситуация, когда при повторном чтении в рамках одной транзакции ранее прочитанные
данные оказываются изменёнными.

phantom reads Чтение «фантомов»


Ситуация, когда при повторном чтении в рамках одной транзакции одна и та же
выборка дает разные множества строк. От неповторяющегося чтения оно отличается
тем, что результат повторного обращения к данным изменился не из-за
изменения/удаления самих этих данных, а из-за появления новых (фантомных)
данных.

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

Под «уровнем изоляции транзакций» понимается степень обеспечиваемой


внутренними механизмами СУБД (то есть не требующей специального
программирования) защиты от всех или некоторых видов вышеперечисленных
несогласованности данных, возникающих при параллельном выполнении транзакций.

Read uncommitted (чтение незафиксированных данных)


Низший (первый) уровень изоляции. Он гарантирует только отсутствие потерянных
обновлений. Если несколько параллельных транзакций пытаются изменять одну и ту
же строку таблицы, то в окончательном варианте строка будет иметь значение,
определенное всем набором успешно выполненных транзакций. При этом возможно
считывание не только логически несогласованных данных, но и данных, изменения
которых ещё не зафиксированы.

Типичный способ реализации данного уровня изоляции — блокировка данных на


время выполнения команды изменения, что гарантирует, что команды изменения
одних и тех же строк, запущенные параллельно, фактически выполнятся
последовательно, и ни одно из изменений не потеряется. Транзакции, выполняющие
только чтение, при данном уровне изоляции никогда не блокируются.

(лечит lost update Потерянное обновление)

Read committed (чтение фиксированных данных)


Большинство промышленных СУБД, в частности, Microsoft SQL Server, PostgreSQL и
Oracle, по умолчанию используют именно этот уровень. На этом уровне
обеспечивается защита от чернового, «грязного» чтения, тем не менее, в процессе
работы одной транзакции другая может быть успешно завершена и сделанные ею
изменения зафиксированы. В итоге первая транзакция будет работать с другим
набором данных.

Реализация завершённого чтения может основываться на одном из двух подходов:


блокировании или версионности.

(лечит dirty read «Грязное» чтение)


Repeatable read (повторяемость чтения)
Уровень, при котором читающая транзакция «не видит» изменения данных, которые
были ею ранее прочитаны. При этом никакая другая транзакция не может изменять
данные, читаемые текущей транзакцией, пока та не окончена.

Блокировки в разделяющем режиме применяются ко всем данным, считываемым


любой инструкцией транзакции, и сохраняются до её завершения. Это запрещает
другим транзакциям изменять строки, которые были считаны незавершённой
транзакцией. Однако другие транзакции могут вставлять новые строки,
соответствующие условиям поиска инструкций, содержащихся в текущей транзакции.
При повторном запуске инструкции текущей транзакцией будут извлечены новые
строки, что приведёт к фантомному чтению. Учитывая то, что разделяющие
блокировки сохраняются до завершения транзакции, а не снимаются в конце каждой
инструкции, степень параллелизма ниже, чем при уровне изоляции READ
COMMITTED. Поэтому пользоваться данным и более высокими уровнями транзакций
без необходимости обычно не рекомендуется.

(лечит non-repeatable read Неповторяющееся чтение)

Serializable (упорядочиваемость)
Самый высокий уровень изолированности; транзакции полностью изолируются друг от
друга, каждая выполняется так, как будто параллельных транзакций не существует. Только
на этом уровне параллельные транзакции не подвержены эффекту «фантомного чтения».

(лечит phantom reads Чтение «фантомов»)

DRY

Don’t repeat yourself это принцип разработки программного обеспечения, нацеленный


на снижение повторения информации различного рода, особенно в системах со
множеством слоёв абстрагирования. Принцип DRY формулируется как: «Каждая часть
знания должна иметь единственное, непротиворечивое и авторитетное представление
в рамках системы».

Исключения - доп валидация полей на фронте

KISS

Keep it simple, stupid принцип проектирования, принятый в ВМС США в 1960. Принцип
KISS утверждает, что большинство систем работают лучше всего, если они остаются
простыми, а не усложняются. Поэтому в области проектирования простота должна быть
одной из ключевых целей, и следует избегать ненужной сложности.
Less is more подход к разработке программного обеспечения, объявляющий простоту
реализации и простоту интерфейса более важными, чем любые другие свойства
системы.

YAGNI

You aren't gonna need it»; с англ. — «Вам это не понадобится») — процесс и принцип
проектирования ПО, при котором в качестве основной цели и/или ценности
декларируется отказ от избыточной функциональности, — то есть отказ добавления
функциональности, в которой нет непосредственной надобности.

Unix way

Пишите программы, которые делают что-то одно и делают это хорошо

SOLID

Это аббревиатура пяти основных принципов проектирования в


объектно-ориентированном программировании.

Single responsibility — принцип единственной ответственности


означает, что каждый объект должен иметь одну обязанность и эта обязанность
должна быть полностью инкапсулирована в класс. Все его сервисы должны быть
направлены исключительно на обеспечение этой обязанности. зависит от потока
влияния

Open-closed — принцип открытости / закрытости


декларирует, что программные сущности (классы, модули, функции и т. п.) должны
быть открыты для расширения, но закрыты для изменения. Это означает, что эти
сущности могут менять свое поведение без изменения их исходного кода.
Следование принципу OCP заключается в том, что программное обеспечение
изменяется не через изменение существующего кода, а через добавление нового кода.

Liskov substitution — принцип подстановки Барбары Лисков


функции, которые используют базовый тип, должны иметь возможность использовать
подтипы базового типа не зная об этом. Следование принципу LSP заключается в том,
что при построении иерархий наследования создаваемые наследники должны
корректно реализовывать поведение базового типа. То есть если базовый тип
реализует определённое поведение, то это поведение должно быть корректно
реализовано и для всех его наследников.
Interface segregation — принцип разделения интерфейса
клиенты не должны зависеть от методов, которые они не используют
То есть если какой-то метод интерфейса не используется клиентом, то изменения
этого метода не должны приводить к необходимости внесения изменений в клиентский
код.
Следование принципу ISP заключается в создании интерфейсов, которые достаточно
специфичны и требуют только необходимый минимум реализаций методов.
Избыточные интерфейсы, напротив, могут требовать от реализующего класса
создание большого количества методов, причём даже таких, которые не имеют смысла
в контексте класса.

Dependency inversion — принцип инверсии зависимостей


модули верхних уровней не должны зависеть от модулей нижних уровней, а оба типа
модулей должны зависеть от абстракций; сами абстракции не должны зависеть от
деталей, а вот детали должны зависеть от абстракций.
Следование принципу инверсии зависимостей «заставляет» реализовывать
высокоуровневые компоненты без встраивания зависимостей от конкретных
низкоуровневых классов, что, например, сильно упрощает замену используемых
зависимостей как по изнес-требованиям, так и для целей тестирования. При этом
зависимость формируется не от конкретной реализации, а от абстракции —
реализуемого зависимостью интерфейса.

TDD

test-driven development или процесс разработки через тестирование


процесс разработки через тестирование — это методология разработки программного
обеспечения, которая основывается на повторении коротких циклов разработки:
изначально пишется тест, покрывающий желаемое изменение, затем пишется
программный код, который реализует желаемое поведение системы и позволит пройти
написанный тест, а затем проводится рефакторинг написанного кода с постоянной
проверкой прохождения всех тестов.

BDD

Behavior-driven development, дословно «разработка через поведение»


BDD методология является расширением TDD в том смысле, что перед тем как
написать какой-либо тест, необходимо сначала описать желаемый результат от
добавляемой функциональности на предметно-ориентированном языке. После того как
это будет проделано, конструкции этого языка переводятся специалистами или
специальным программным обеспечением в описание теста.

DDD
domain-driven design Предметно-ориентированное проектирование
это набор принципов и схем, направленных на создание оптимальных систем
объектов. Сводится к созданию программных абстракций, которые называются
моделями предметных областей. В эти модели входит бизнес-логика,
устанавливающая связь между реальными условиями области применения продукта и
кодом.

Концепции:

● Ограниченные связи - Точно определить контекст, в котором используется


модель. Определить границы использования данной модели и её
характеристики.
● Целостность Постоянное объединение кусков кода от различных
разработчиков и проверка работоспособности посредством тестирования. Это
позволяет держаться всем разработчикам в одной большой концепции.
● Взаимосвязь На этапе проектирования точно обозначьте, что именно выполняет
каждая модель и как она взаимосвязана с другими моделями. В конечном итоге у
вас должна получиться карта взаимосвязей моделей.
● Общий язык между программистом и бизнесом

Элементы:

● Ограниченный контекст - Это подмножество более большой доменной


модели. Можно сказать, что ограниченный контекст строится, как отдельная
уменьшенная доменная модель с использованием терминов единого языка,
характерных для выбранной подобласти.
● Сущность (определяется id и существует всегда)
● Объект-значение (определяется атрибутами и неизменяем после создания)
● Агрегат - составная сущность (из сущностей и объектов-значений),
определяется идентификатором. Поддерживает транзакционность изменений
над всем своим содержимым. Другие элементы домена не должны знать о
содержимом агрегата. Агрегат - граница уникальности для сущности, одна
сущность не может быть одновременно в нескольких агрегатах. Если одна
сущность должна быть в нескольких агрегатах, то её саму надо считать
агрегатом.
● Служба - это функции, которые не привязаны к сущностям или ценностным
объектам. Сервисы без состояния. Могут обращаться к репозиториям и другим
сервисам.
● Репозитории — вещь для создания объектов, используется только агрегатов. В
доменной модели только интерфейс. А реализация на инфраструктурном слое.
● Исключения - методы либо бросают исключения, либо делают работу
● DTO - объект для передачи данных
ATDD

"Разработка через приемочные тесты" – acceptance test driven development


Разработка через тестирование (TDD) – отличный способ повысить качество и
надежность кода. Этот же подход может быть распространен и на разработку
требований.

Общий смысл в том, что прежде чем что-то делать, надо придумать критерий
выполненной работы и критерий того, что работа сделана правильно.

Эти критерии описываются на понятном заказчику языке в виде готовых сценариев.


Сценарии моделируют то, как проектируемая фича будет использоваться в
дальнейшем. Если сценарий реализован и ожидаемый в нем результат может быт
получен на практике, значит задача решена корректно и работу можно считать
выполненной. Набор таких сценариев и называется приемочными тестами.
Приемочные тесты фокусируются на поведении системы с точки зрения человека, а не
на внутреннем устройстве и на технических деталях реализации.

Для приемочных тестов используется подход Given – When – Then (GWT). Суть та же,
только с другого ракурса.

Given описывает что «дано», т.е. состояние системы в начальный момент времени
When задает непосредственно триггер, который должен привести к результату. Чаще
всего это какое-то действие пользователя.
Then определяет результат этого действия, т.е. является критерием приемки.

UNIT TESTS

Arrange – Act – Assert (AAA)


Это означает, что в тестах должны быть явные части, отвечающие за подготовку
данных — arrange, само действие, результат которого надо проверить – act, и
собственно проверка, что реальность совпала с ожиданиями – assert.

GRASP

GRASP (General Responsibility Assignment Software Patterns) — шаблоны


проектирования, используемые для решения общих задач по назначению
обязанностей классам и объектам.
Шаблоны GRASP являются скорее не паттернами проектирования (как GoF'овские), а
фундаментальными принципами распределения ответственности между классами.

Информационный эксперт (Information Expert)


Ответственность должна быть назначена тому, кто владеет максимумом необходимой
информации для исполнения — информационному эксперту.
информация должна обрабатываться там, где она содержится.

Создатель (Creator)
создавать экземпляры класса должен класс, которому они нужны.
Класс должен создавать экземпляры тех классов, которые он может:
● Содержать или агрегировать;
● Записывать;
● Использовать;
● Инициализировать, имея нужные данные.

Контроллер (Controller)
Отвечает за операции, запросы на которые приходят от пользователя, и может
выполнять сценарии одного или нескольких вариантов использования (например,
создание и удаление);
Не выполняет работу самостоятельно, а делегирует компетентным исполнителям;

Слабое зацепление (Low Coupling)


«Слабое» зацепление — распределение ответственностей и данных, обеспечивающее
взаимную независимость классов. Класс со «слабым» зацеплением:

Имеет слабую зависимость от других классов;


Не зависит от внешних изменений (изменение в одном классе оказывает слабое
влияние на другие классы);
Прост для повторного использования.

Высокая связность (High Cohesion)


Высокая связность означает, что обязанности данного элемента тесно связаны и
сфокусированы. Разбиение программ на классы и подсистемы является примером
деятельности, которая увеличивает связность системы.

И наоборот, низкая связность — это ситуация, при которой данный элемент имеет
слишком много несвязанных обязанностей. Элементы с низкой связностью часто
страдают от того, что их трудно понять, трудно использовать, трудно поддерживать.

Полиморфизм (Polymorphism)
Устройство и поведение системы:

Определяется данными;
Задано полиморфными операциями её интерфейса. (способность функции
обрабатывать данные разных типов)
один интерфейс — много реализаций

Чистое изготовление (Pure Fabrication)


Необходимо обеспечивать low coupling и high cohesion. Для этой цели может
понадобиться синтезировать искусственную сущность. Паттерн Pure Fabrication
говорит о том, что не стоит стесняться это сделать. В качестве примера можно
рассматривать фасад к базе данных. Это чисто искусственный объект, не имеющий
аналогов в предметной области. В общем случае любой фасад относится к Pure
Fabrication (если это конечно не архитектурный фасад в соответствующим
приложении).

Перенаправление (Indirection)
Необходимо распределить обязанности между объектами, избежав прямого
связывания. Для этого можно присвоить обязанности по обеспечению связи между
компонентами или службами промежуточному объекту.

Если переводить на русский язык, то паттерн подразумевает следующее: любой


объект в коде необходимо вызывать через его интерфейс (тот самый промежуточный
объект)

Устойчивость к изменениям (Protected Variations)


Необходимо спроектировать систему так, чтобы изменение одних ее элементов не
влияло на другие. В качестве решения предлагается идентифицировать точки
возможных изменений или неустойчивости и распределить обязанности таким
образом, чтобы обеспечить устойчивую работу системы.

На самом деле, это не паттерн, а цель, достигаемая соблюдением остальных


паттернов.

Design Patterns

Паттерн проектирования — это часто встречающееся решение определенной


проблемы при проектировании архитектуры программ.

Порождающие паттерны

отвечают за удобное и безопасное создание новых объектов или даже целых семейств
объектов.

Фабричный метод
определяет общий интерфейс для создания объектов в суперклассе, позволяя
подклассам изменять тип создаваемых объектов.
Паттерн Фабричный метод предлагает создавать объекты не напрямую, используя
оператор new, а через вызов особого фабричного метода. Не пугайтесь, объекты всё
равно будут создаваться при помощи new, но делать это будет фабричный метод.

Абстрактная фабрика
позволяет создавать семейства связанных объектов, не привязываясь к конкретным
классам создаваемых объектов.
Для начала паттерн Абстрактная фабрика предлагает выделить общие интерфейсы
для отдельных продуктов, составляющих семейства. Так, все вариации кресел получат
общий интерфейс Кресло, все диваны реализуют интерфейс Диван и так далее.

Далее вы создаёте абстрактную фабрику — общий интерфейс, который содержит


методы создания всех продуктов семейства (например, создатьКресло, создатьДиван и
создатьСтолик). Эти операции должны возвращать абстрактные типы продуктов,
представленные интерфейсами, которые мы выделили ранее — Кресла, Диваны и
Столики.

Для каждой вариации семейства продуктов мы должны создать свою собственную


фабрику, реализовав абстрактный интерфейс. Фабрики создают продукты одной
вариации.

Строитель
позволяет создавать сложные объекты пошагово. Строитель даёт возможность
использовать один и тот же код строительства для получения разных представлений
объектов.
Паттерн Строитель предлагает вынести конструирование объекта за пределы его
собственного класса, поручив это дело отдельным объектам, называемым
строителями.

Прототип
позволяет копировать объекты, не вдаваясь в подробности их реализации.
Паттерн Прототип поручает создание копий самим копируемым объектам. Он вводит
общий интерфейс для всех объектов, поддерживающих клонирование. Это позволяет
копировать объекты, не привязываясь к их конкретным классам. Обычно такой
интерфейс имеет всего один метод clone.

Одиночка
гарантирует, что у класса есть только один экземпляр, и предоставляет к нему
глобальную точку доступа.

Структурные паттерны

отвечают за построение удобных в поддержке иерархий классов.


Адаптер
позволяет объектам с несовместимыми интерфейсами работать вместе.
Это объект-переводчик, который трансформирует интерфейс или данные одного
объекта в такой вид, чтобы он стал понятен другому объекту.

Мост
разделяет один или несколько классов на две отдельные иерархии — абстракцию и
реализацию, позволяя изменять их независимо друг от друга.
Паттерн Мост предлагает заменить наследование агрегацией или композицией. Для
этого нужно выделить одну из таких «плоскостей» в отдельную иерархию и ссылаться
на объект этой иерархии, вместо хранения его состояния и поведения внутри одного
класса.

У вас есть класс геометрических Фигур, который имеет подклассы Круг и Квадрат. Вы
хотите расширить иерархию фигур по цвету, то есть иметь Красные и Синие фигуры.
Но чтобы всё это объединить, вам придётся создать 4 комбинации подклассов, вроде
СиниеКруги и КрасныеКвадраты.

Корень проблемы заключается в том, что мы пытаемся расширить классы фигур сразу
в двух независимых плоскостях — по виду и по цвету. Именно это приводит к
разрастанию дерева классов.

Таким образом, мы можем сделать Цвет отдельным классом с подклассами Красный и


Синий. Класс Фигур получит ссылку на объект Цвета и сможет делегировать ему
работу, если потребуется. Такая связь и станет мостом между Фигурами и Цветом. При
добавлении новых классов цветов не потребуется трогать классы фигур и наоборот.

Компоновщик
Агрегат из DDD

Декоратор
позволяет динамически добавлять объектам новую функциональность, оборачивая их
в полезные «обёртки».
Декоратор имеет альтернативное название — обёртка. Оно более точно описывает
суть паттерна: вы помещаете целевой объект в другой объект-обёртку, который
запускает базовое поведение объекта, а затем добавляет к результату что-то своё.
Оба объекта имеют общий интерфейс, поэтому для пользователя нет никакой
разницы, с каким объектом работать — чистым или обёрнутым.

Фасад
предоставляет простой интерфейс к сложной системе классов, библиотеке или
фреймворку.

Легковес
позволяет вместить бóльшее количество объектов в отведённую оперативную память.
Легковес экономит память, разделяя общее состояние объектов между собой, вместо
хранения одинаковых данных в каждом объекте.
Паттерн Легковес предлагает не хранить в классе внешнее состояние, а передавать
его в те или иные методы через параметры. Таким образом, одни и те же объекты
можно будет повторно использовать в различных контекстах. Но главное —
понадобится гораздо меньше объектов, ведь теперь они будут отличаться только
внутренним состоянием, а оно имеет не так много вариаций.

Заместитель
позволяет подставлять вместо реальных объектов специальные объекты-заменители.
Эти объекты перехватывают вызовы к оригинальному объекту, позволяя сделать
что-то до или после передачи вызова оригиналу.
Паттерн Заместитель предлагает создать новый класс-дублёр, имеющий тот же
интерфейс, что и оригинальный служебный объект. При получении запроса от клиента
объект-заместитель сам бы создавал экземпляр служебного объекта и
переадресовывал бы ему всю реальную работу.

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

решают задачи эффективного и безопасного взаимодействия между объектами


программы.

Цепочка обязанностей
позволяет передавать запросы последовательно по цепочке обработчиков. Каждый
последующий обработчик решает, может ли он обработать запрос сам и стоит ли
передавать запрос дальше по цепи.
Паттерн предлагает связать объекты обработчиков в одну цепь. Каждый из них будет
иметь ссылку на следующий обработчик в цепи. Таким образом, при получении
запроса обработчик сможет не только сам что-то с ним сделать, но и передать
обработку следующему объекту в цепочке.

Команда
превращает запросы в объекты, позволяя передавать их как аргументы при вызове
методов, ставить запросы в очередь, логировать их, а также поддерживать отмену
операций.
Паттерн Команда предлагает больше не отправлять такие вызовы напрямую. Вместо
этого каждый вызов, отличающийся от других, следует завернуть в собственный класс
с единственным методом, который и будет осуществлять вызов. Такие объекты
называют командами.

Итератор
даёт возможность последовательно обходить элементы составных объектов, не
раскрывая их внутреннего представления.
Идея паттерна Итератор состоит в том, чтобы вынести поведение обхода коллекции из
самой коллекции в отдельный класс.
Посредник
позволяет уменьшить связанность множества классов между собой, благодаря
перемещению этих связей в один класс-посредник.
Паттерн Посредник заставляет объекты общаться не напрямую друг с другом, а через
отдельный объект-посредник, который знает, кому нужно перенаправить тот или иной
запрос. Благодаря этому, компоненты системы будут зависеть только от посредника, а
не от десятков других компонентов.

Снимок/Хранитель
позволяет сохранять и восстанавливать прошлые состояния объектов, не раскрывая
подробностей их реализации.
Паттерн Снимок поручает создание копии состояния объекта самому объекту, который
этим состоянием владеет. Вместо того, чтобы делать снимок «извне», наш редактор
сам сделает копию своих полей, ведь ему доступны все поля, даже приватные.

Паттерн предлагает держать копию состояния в специальном объекте-снимке с


ограниченным интерфейсом, позволяющим, например, узнать дату изготовления или
название снимка. Но, с другой стороны, снимок должен быть открыт для своего
создателя, позволяя прочесть и восстановить его внутреннее состояние.

Наблюдатель
создаёт механизм подписки, позволяющий одним объектам следить и реагировать на
события, происходящие в других объектах.
Паттерн Наблюдатель предлагает хранить внутри объекта издателя список ссылок на
объекты подписчиков, причём издатель не должен вести список подписки
самостоятельно. Он предоставит методы, с помощью которых подписчики могли бы
добавлять или убирать себя из списка.

Состояние
позволяет объектам менять поведение в зависимости от своего состояния. Извне
создаётся впечатление, что изменился класс объекта.
Паттерн Состояние предлагает создать отдельные классы для каждого состояния, в
котором может пребывать объект, а затем вынести туда поведения, соответствующие
этим состояниям.

Вместо того, чтобы хранить код всех состояний, первоначальный объект, называемый
контекстом, будет содержать ссылку на один из объектов-состояний и делегировать
ему работу, зависящую от состояния.

Стратегия
определяет семейство схожих алгоритмов и помещает каждый из них в собственный
класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения
программы.

Паттерн Стратегия предлагает определить семейство схожих алгоритмов, которые


часто изменяются или расширяются, и вынести их в собственные классы, называемые
стратегиями.
Вместо того, чтобы изначальный класс сам выполнял тот или иной алгоритм, он будет
играть роль контекста, ссылаясь на одну из стратегий и делегируя ей выполнение
работы. Чтобы сменить алгоритм, вам будет достаточно подставить в контекст другой
объект-стратегию.

Шаблонный метод
определяет скелет алгоритма, перекладывая ответственность за некоторые его шаги
на подклассы. Паттерн позволяет подклассам переопределять шаги алгоритма, не
меняя его общей структуры.

Паттерн Шаблонный метод предлагает разбить алгоритм на последовательность


шагов, описать эти шаги в отдельных методах и вызывать их в одном шаблонном
методе друг за другом.

Это позволит подклассам переопределять некоторые шаги алгоритма, оставляя без


изменений его структуру и остальные шаги, которые для этого подкласса не так важны.

Посетитель
позволяет добавлять в программу новые операции, не изменяя классы объектов, над
которыми эти операции могут выполняться.
Паттерн Посетитель предлагает разместить новое поведение в отдельном классе,
вместо того чтобы множить его сразу в нескольких классах. Объекты, с которыми
должно было быть связано поведение, не будут выполнять его самостоятельно.
Вместо этого вы будете передавать эти объекты в методы посетителя.

Как трейт в php.

Типы и структуры данных

Связные списки
Связный список состоит из группы узлов, которые вместе образуют
последовательность. Каждый узел содержит две вещи: фактические данные, которые в
нем хранятся (это могут быть данные любого типа) и указатель (или ссылку) на
следующий узел в последовательности. Также существуют двусвязные списки: в них у
каждого узла есть указатель и на следующий, и на предыдущий элемент в списке.

Основные операции в связном списке включают добавление, удаление и поиск


элемента в списке.

Стеки
Стек — это базовая структура данных, которая позволяет добавлять или удалять
элементы только в её начале. Она похожа на стопку книг: если вы хотите взглянуть на
книгу в середине стека, сперва придется убрать лежащие сверху.

Стек организован по принципу LIFO (Last In First Out, «последним пришёл — первым
вышел») . Это значит, что последний элемент, который вы добавили в стек, первым
выйдет из него.

Деки
стек с двумя концами. Действительно, несмотря конкретный перевод, дек можно
определять не только как двухстороннюю очередь, но и как стек, имеющий два конца.
Это означает, что данный вид списка позволяет добавлять элементы в начало и в
конец, и то же самое справедливо для операции извлечения.
Эта структура одновременно работает по двум способам организации данных: FIFO и
LIFO. Поэтому ее допустимо отнести к отдельной программной единице, полученной в
результате суммирования двух предыдущих видов списка.

Очереди
Очередь устроена по принципу FIFO (First In First Out, «первый пришёл — первый
вышел»). Это значит, что удалить элемент можно только после того, как были убраны
все ранее добавленные элементы.

Очередь позволяет выполнять две основных операции: добавлять элементы в конец


очереди (enqueue) и удалять первый элемент (dequeue).

Множества
Множество хранит значения данных без определенного порядка, не повторяя их. Оно
позволяет не только добавлять и удалять элементы: есть ещё несколько важных
функций, которые можно применять к двум множествам сразу.

● Объединение комбинирует все элементы из двух разных множеств, превращая


их в одно (без дубликатов).
● Пересечение анализирует два множества и создает еще одно из тех элементов,
которые присутствуют в обоих изначальных множествах.
● Разность выводит список элементов, которые есть в одном множестве, но
отсутствуют в другом.
● Подмножество выдает булево значение, которое показывает, включает ли одно
множество все элементы другого множества.
Карта
Map — это структура, которая хранит данные в парах ключ/значение, где каждый ключ
уникален. Иногда её также называют ассоциативным массивом или словарём. Map
часто используют для быстрого поиска данных. Она позволяет делать следующие
вещи:

● добавлять пары в коллекцию;


● удалять пары из коллекции;
● изменять существующей пары;
● искать значение, связанное с определенным ключом.

Хэш-таблицы
Хэш-таблица — это похожая на Map структура, которая содержит пары ключ/значение.
Она использует хэш-функцию для вычисления индекса в массиве из блоков данных,
чтобы найти желаемое значение.

Двоичное дерево поиска


Дерево — это структура данных, состоящая из узлов. Ей присущи следующие
свойства:

Каждое дерево имеет корневой узел (вверху).


Корневой узел имеет ноль или более дочерних узлов.
Каждый дочерний узел имеет ноль или более дочерних узлов, и так далее.

У двоичного дерева поиска есть два дополнительных свойства:

Каждый узел имеет до двух дочерних узлов (потомков).


Каждый узел меньше своих потомков справа, а его потомки слева меньше его самого.

Двоичные деревья поиска позволяют быстро находить, добавлять и удалять элементы.


Они устроены так, что время каждой операции пропорционально логарифму общего
числа элементов в дереве.

Префиксное дерево
Префиксное (нагруженное) дерево — это разновидность дерева поиска. Оно хранит
данные в метках, каждая из которых представляет собой узел на дереве. Такие
структуры часто используют, чтобы хранить слова и выполнять быстрый поиск по ним
— например, для функции автозаполнения.
Каждый узел в языковом префиксном дереве содержит одну букву слова. Чтобы
составить слово, нужно следовать по ветвям дерева, проходя по одной букве за раз.
Дерево начинает ветвиться, когда порядок букв отличается от других имеющихся в нем
слов или когда слово заканчивается. Каждый узел содержит букву (данные) и булево
значение, которое указывает, является ли он последним в слове.

Двоичная куча
Двоичная куча — ещё одна древовидная структура данных. В ней у каждого узла не
более двух потомков. Также она является совершенным деревом: это значит, что в ней
полностью заняты данными все уровни, а последний заполнен слева направо.

Двоичная куча может быть минимальной или максимальной. В максимальной куче


ключ любого узла всегда больше ключей его потомков или равен им. В минимальной
куче всё устроено наоборот: ключ любого узла меньше ключей его потомков или равен
им.

Граф
Графы — это совокупности узлов (вершин) и связей между ними (рёбер). Также их
называют сетями.

По такому принципу устроены социальные сети: узлы — это люди, а рёбра — их


отношения.

Графы делятся на два основных типа: ориентированные и неориентированные. У


неориентированных графов рёбра между узлами не имеют какого-либо направления,
тогда как у рёбер в ориентированных графах оно есть.

Чаще всего граф изображают в каком-либо из двух видов: это может быть список
смежности или матрица смежности
уществуют специальные алгоритмы для просмотра рёбер и вершин в графах — так
называемые алгоритмы обхода. К их основным типам относят поиск в ширину
(breadth-first search) и в глубину (depth-first search). Как вариант, с их помощью можно
определить, насколько близко к корневому узлу находятся те или иные вершины
графа.

Массивы
Массив – это структура данных с фиксированным и упорядоченным набором
однотипных элементов (компонентов). Доступ к какому-либо из элементов массива
осуществляется по имени и номеру (индексу) этого элемента. Количество индексов
определяет размерность массива.
Сложность алгоритмов

О(1) - постоянное время


O(log n) - логарифмическое время
О(n) - линейное время
O(n log n) - ?
О(n^2) - квадратичное время
О(2^n)
O(n!)

пример - вставка в конец массива или вставка в начало списка или вставка в очередь
или стек - постоянное время
пример - вставка в начало массива - линейное время
пример - сортировки - обычно логарифмическое время
пример - что-то в цикле - обычно квадратичное время

ООП

Наследование
класс может наследовать поведения и данные от другого класса

Полиморфизм
способность одним методом обрабатывать разные типы данных

● Ad-hoc-полиморфизм ( поддерживается во многих языках посредством


перегрузки функций и методов, а в слабо типизированных — также посредством
приведения типов.)
● Параметрический полиморфизм (подстановка типов данных в java
структурах)
● Полиморфизм подтипов (один интерфейс — много реализаций)

Инкапсуляция
объект содержит поведения и данные

Абстракция
контекстное понимание предмета, формализуемое в виде класса

Агрегация (Композиция)
CQRS
Command-query separation (CQS)
Принцип гласит, что метод должен быть либо командой, выполняющей какое-то
действие, либо запросом, возвращающим данные, но не одновременно. Другими
словами, задавание вопроса не должно менять ответ. Более формально, возвращать
значение можно только чистым (т.е. детерминированным и не имеющим побочных
эффектов) методом. Следует отметить, что строгое соблюдение этого принципа делает
невозможным отслеживание количества вызовов запросов.
Суть в отсутствии побочных действий

Не сказать что исчерпывающее определение, но сейчас я попробую объяснить что именно


Фаулер имел в виду.
К настоящему времени сложилась такая ситуация что практические все работают с
моделью данных как с CRUD хранилищем. CQRS предлагает альтернативный подход, но
затрагивает не только модель данных. Если вы используете CQRS, то это сильно
отражается на архитектуре вашего приложения.

Первое что бросается в глаза это то что у вас уже две модели данных, одна для чтения
(Queries), одна для записи (Commands). И обычно это значит что у вас еще и две базы
данных. И так как мы используем CQRS + Event Sourcing, то write-база (write-модель) — это
Event Store, что-то вроде лога всех действий пользователя (на самом деле не всех, а
только тех которые важны с точки зрения бизнес-модели и влияют на построение
read-базы). А read-база — это в общем случае денормализировнное хранилище тех
данных, которые вам нужны для отображения пользователю. Почему я сказал что
read-база денормализированная? Вы конечно можете использовать любую структуру
данных в качестве read-модели, но я считаю что при использовании CQRS + Event Sourcing
не стоит сильно заморачиваться над нормализвацией read-базы, так как она может быть
полностью перестроена в любое время. И это большой плюс, особенно если вы не хотите
использовать реляционные базы данных и смотрите в сторону NoSQL.
Write-база вообще представляет собой одну коллекцию ивентов. То есть тут тоже нету
смысла использовать реляционную базу.

DI

Внедрение зависимости (англ. Dependency injection, DI)


предоставления внешней зависимости программному компоненту. Является
специфичной формой «инверсии управления» (англ. Inversion of control, IoC), когда она
применяется к управлению зависимостями. В полном соответствии с принципом
единственной обязанности объект отдаёт заботу о построении требуемых ему
зависимостей внешнему, специально предназначенному для этого общему
механизму[1].
Внедрение зависимости более гибко, потому что становится легче создавать
альтернативные реализации данного типа сервиса, а потом указывать, какая именно
реализация должна быть использована в, например, конфигурационном файле, без
изменений в объектах, которые этот сервис используют. Это особенно полезно в
юнит-тестировании, потому что вставить реализацию «заглушки» сервиса в
тестируемый объект очень просто.

ONION

The Onion Architecture is an Architectural Pattern that enables maintainable and


evolutionary enterprise systems. It is intended for use at a Solution/System level.

Good Coupling
The primary proposition of this architecture is good coupling.
What is coupling ? It is the level of dependency of one thing upon another. The higher the
coupling, the lower the ability to change and evolve the system.
Dependencies should be inward and never outward. Code should depend only on the same
layer or layers more central to itself.

Behaviour Contracts
Business Logic behaviour is declared as contracts with the use of interfaces in a
Object-Oriented context.

Separation of concerns
Each layer bounds together concepts that will have a similar rate of change.

Domain Model
The very centre of the Model, this layer can have dependencies only on itself. It represents
the Entities of the Business and the Behaviour of these Entities.

Domain Services
This layer contains the implementation of the behaviour contracts defined in the Model layer.

Application Services
This layer is the bridge between external infrastructure and the domain layers. The domain
layers often need information or functionality in order to complete business functionality,
however they should not directly depend on these. Instead, the application layer needs to
depend on the the contracts defined in the Domain Services layer.

External Services
Databases, Messaging systems, Notification systems, User Interface, etc.

CI
Непрерывная интеграция (CI, англ. Continuous Integration) — практика разработки
программного обеспечения, которая заключается в постоянном слиянии рабочих копий
в общую основную ветвь разработки (до нескольких раз в день) и выполнении частых
автоматизированных сборок проекта для скорейшего выявления потенциальных
дефектов и решения интеграционных проблем. В обычном проекте, где над разными
частями системы разработчики трудятся независимо, стадия интеграции является
заключительной. Она может непредсказуемо задержать окончание работ. Переход к
непрерывной интеграции позволяет снизить трудоёмкость интеграции и сделать её
более предсказуемой за счёт наиболее раннего обнаружения и устранения ошибок и
противоречий, но основным преимуществом является сокращение стоимости
исправления дефекта, за счёт раннего его выявления.

CD
Непрерывная доставка (англ. Continuous delivery или CD, или CDE) — это подход к
разработке программного обеспечения, при котором программное обеспечение
производится короткими итерациями, гарантируя, что ПО является стабильным и
может быть передано в эксплуатацию в любое время, а передача его происходит
вручную[1]. Целью является сборка, тестирование и релиз программного обеспечения
с большей скоростью и частотой. Подход позволяет уменьшить стоимость, время и
риски внесения изменений путём более частных мелких обновлений в
продакшн-приложение.

CD отличается от непрерывного развёртывания, в котором ПО также производится


короткими циклами через автоматическое развёртывание, в противоположность
ручному.

EDA

Архитектура, управляемая событиями (англ. event-driven architecture, EDA) является


шаблоном архитектуры программного обеспечения, позволяющим создание, определение,
потребление и реакцию на события.

Событие можно определить как «существенное изменение состояния»[1]. Например, когда


покупатель приобретает автомобиль, состояние автомобиля изменяется с «продаваемого»
на «проданный». Системная архитектура продавца автомобилей может рассматривать это
изменение состояния как событие, создаваемое, публикуемое, определяемое и
потребляемое различными приложениями в составе архитектуры.

Структура события
Событие может состоять из двух частей: заголовка события и тела события.

Уровни потока событий

Управляемая событиями архитектура включает поставщики событий, которые создают


потоки событий, и потребители событий, которые прослушивают эти события.

События доставляются практически мгновенно, что позволяет потребителям


немедленно реагировать на происходящие события. Поставщики не связаны с
потребителями — ни один поставщик не знает, кто прослушивает его события.
Потребители также не зависят друг от друга, и каждый из них получает все события.

В основе управляемой событиями архитектуры может лежать модель публикации и


подписки или модель потока событий.

● Публикация и подписка. Инфраструктура обмена сообщениями поддерживает


список подписок. Каждое публикуемое событие отправляется каждому
подписчику. Полученное сообщение нельзя воспроизвести повторно. Также оно
не доставляется тем подписчикам, которые добавляются позднее,
● Потоковая передача событий. Все события записываются в журнал. События
в пределах каждой секции строго упорядочены и сохраняются в течение долгого
времени. Клиенты не подписываются на поток, а просто считывают события из
любой его части. Каждый клиент самостоятельно управляет своим положением
в потоке. Это означает, что клиент может подключиться в любое время и (или)
прослушать события повторно.
На стороне получателя есть несколько распространенных вариантов реализации:

● Обработка простых событий. Каждое событие немедленно запускает


действие в объекте-получателе.
● Обработка сложных событий. Объект-получатель обрабатывает
последовательность событий и отслеживает в них определенные
закономерности с помощью некоторого технологического решения
● Обработка потока событий. Платформу потоковой передачи данных можно
использовать как конвейер для приема событий и передачи их в обработчики
потоков. Обработчики потоков определенным образом реагируют на эти
процессы или преобразовывают поток. Может существовать несколько
обработчиков потока для разных подсистем приложения.

Плюсы

● Слабую связанность компонентов приложения и, как следствие, — хорошие


возможности для его дальнейшего расширения.
● Открытый API. Это не очевидно сначала, но, ничего специально не сделав, мы
создали API, который позволит другим разработчикам создавать расширения
без вмешательства в основной код проекта. И любой внешний скрипт сможет
взаимодействовать с нашим приложением.
● Легкость в тестировании. Из-за того, что модули связаны только событиями,
для их тестирования достаточно тригеррить нужные события с нужными
данными, без зависимостей от работы сторонних модулей

Минусы

● «Широковещательность». Нельзя отправить сообщение конкретному


слушателю. В нашем случае это не важно.
● «Незащищенность». Любой объект может слушать любое событие и любой
объект может сгенерировать событие. В нашем случае важно второе. То есть
слушатели не могут доверять данным, которые им передаются. Решается
проверкой данных в слушателе.
● Кто первый — того и тапки. Любой слушатель может прекратить дальнейшее
оповещение о событии. В теории не решается никак. Частично решается
контролем очередности подключения модулей/подписки на события.

MVC
Основная цель применения этой концепции состоит в отделении бизнес-логики
(модели) от её визуализации (представления, вида).

● Модель (Model) предоставляет данные и реагирует на команды


контроллера, изменяя своё состояние[1].
● Представление (View) отвечает за отображение данных модели
пользователю, реагируя на изменения модели[1].
● Контроллер (Controller) интерпретирует действия пользователя,
оповещая модель о необходимости изменений[1].

MVVM
Используется для разделения модели и её представления, что необходимо для их
изменения отдельно друг от друга. Например, разработчик задаёт логику работы с
данными, а дизайнер работает с пользовательским интерфейсом.

● Модель (англ. Model) (так же, как в классической MVC) представляет собой
логику работы с данными и описание фундаментальных данных, необходимых
для работы приложения.
● Представление (англ. View) — графический интерфейс (окна, списки, кнопки и т.
п.). Выступает подписчиком на событие изменения значений свойств или
команд, предоставляемых Моделью Представления. В случае, если в Модели
Представления изменилось какое-либо свойство, то она оповещает всех
подписчиков об этом, и Представление, в свою очередь, запрашивает
обновлённое значение свойства из Модели Представления. В случае, если
пользователь воздействует на какой-либо элемент интерфейса, Представление
вызывает соответствующую команду, предоставленную Моделью
Представления.
● Модель Представления (англ. ViewModel) — с одной стороны, абстракция
Представления, а с другой — обёртка данных из Модели, подлежащиx
связыванию. То есть, она содержит Модель, преобразованную к
Представлению, а также команды, которыми может пользоваться
Представление, чтобы влиять на Модель.

Признаки:

● Двухсторонняя коммуникация с представлением;


● View-модель — это абстракция представления. Обычно означает, что свойства
представления совпадают со свойствами View-модели / модели
● View-модель не имеет ссылки на интерфейс представления (IView). Изменение
состояния View-модели автоматически изменяет представление и наоборот,
поскольку используется механизм связывания данных (Bindings)
● Один экземпляр View-модели связан с одним отображением.
MVP
Элемент Presenter в данном шаблоне берёт на себя функциональность посредника
(аналогично контроллеру в MVC) и отвечает за управление событиями
пользовательского интерфейса (например, использование мыши) так же, как в других
шаблонах обычно отвечает представление.

● Модель (англ. Model) — данные для отображения;


● Вид (англ. View) — реализует отображение данных (из Модели), обращается к
Presenter за обновлениями, перенаправляет события от пользователя в
Presenter;
● Представитель (англ. Presenter) — реализует взаимодействие между Моделью
и Видом и содержит в себе всю логику представления данных о предметной
области; при необходимости получает данные из хранилища и преобразует для
отображения во View.

Признаки:

● Двухсторонняя коммуникация с представлением;


● Представление взаимодействует напрямую с презентером, путем вызова
соответствующих функций или событий экземпляра презентера;
● Презентер взаимодействует с View путем использования специального
интерфейса, реализованного представлением;
● Один экземпляр презентера связан с одним отображением.

Общие правила выбора паттерна

MVVM

Используется в ситуации, когда возможно связывание данных без необходимости


ввода специальных интерфейсов представления (т.е. отсутствует необходимость
реализовывать IView);

MVP

Используется в ситуации, когда невозможно связывание данных (нельзя использовать


Binding);

MVC

Используется в ситуации, когда связь между представление и другими частями


приложения невозможна (и Вы не можете использовать MVVM или MVP);
git rebase vs git merge

В первую очередь нужно понимать, что команда git rebase помогает решить ту же
проблему, что и команда git merge. Обе команды предназначены для включения
изменений из одной ветки в другую, но делают это по-разному.

С другой стороны, это означает, что каждый раз, когда вам будет необходимо включить
вышестоящие изменения, в функциональную ветку будет попадать внешний коммит
слияния. Если работа в главной ветке ведется активно, история вашей
функциональной ветки быстро засорится.

Слияние (merge) — это отличная неразрушающая операция.


Существующие ветки никак не изменяются. Эта операция позволяет избегать
потенциальных проблем, связанных с выполнением команды rebase (и
описанных ниже).

Вместо слияния можно выполнить перебазирование функциональной ветки


(feature) на основную (master) с помощью следующих команд:

В результате вся функциональная ветка окажется поверх главной, включая в


себя все новые коммиты в главной ветке. Если вместо команды merge при
коммитах используется rebase, эта команда перезаписывает историю проекта,
создавая новые коммиты для каждого коммита в исходной ветке.

Главное преимущество rebase — более чистая история проекта.


Во-первых, эта команда устраняет ненужные коммиты слияния, необходимые
для git merge. Во-вторых, как показано на рисунке выше, команда rebase
создает идеальную линейную историю проекта — вы сможете отследить
функционал до самого начала проекта без каких-либо форков.

Однако такая безупречная история коммитов требует определенных жертв:


жертвовать приходится безопасностью и отслеживаемостью. Если не следовать
Золотому правилу Rebase, перезапись истории проекта может обернуться
катастрофическими последствиями для совместных рабочих процессов. Кроме
того, при выполнении rebase теряется контекст, доступный в коммите со
слиянием: вы не сможете увидеть, когда вышестоящие изменения были
включены в функционал.

Золотое правило для команды git rebase — никогда не использовать ее в


публичных ветках.
Event Sourcing

Идея Event Sourcing в том чтобы записывать каждое событие, которое меняет
состояние приложения в базу данных. Таким образом получается что мы храним не
состояние наших сущностей, а все события которые к ним относятся. Однако мы
привыкли к тому чтобы манипулировать именно состоянием, оно храниться у нас в
базе и мы всегда можем его посмотреть.
В случае с Event Sourcing мы тоже оперируем с состоянием сущности. Но в отличии от
обычной модели мы это состоянием не храним, а воспроизводим каждый раз при
обращении.

На самом же деле репозиторий не берет из базы готовое состояние агрегата UserAR


(AR = Aggregate Root), он выбирает из базы все события которые ассоциируются с
этим юзером, и потом воспроизводит их по порядку передавая в метод On() агрегата.

GraphQL

В двух словах, GraphQL это синтаксис, который описывает как запрашивать данные, и,
в основном, используется клиентом для загрузки данных с сервера. GraphQL имеет три
основные характеристики:

● Позволяет клиенту точно указать, какие данные ему нужны.


● Облегчает агрегацию данных из нескольких источников.
● Использует систему типов для описания данных.

На практике GraphQL API построен на трёх основных строительных блоках: на схеме


(schema), запросах (queries) и распознавателях (resolvers).

REST
REST расшифровывается как REpresentational State Transfer. Это был термин,
первоначально введен Роем Филдингом (Roy Fielding), который также был одним из
создателей протокола HTTP. Отличительной особенностью сервисов REST является
то, что они позволяют наилучшим образом использовать протокол HTTP. Теперь
давайте кратко рассмотрим HTTP.

Ресурс

Ресурс — это ключевая абстракция, на которой концентрируется протокол HTTP.


Ресурс — это все, что вы хотите показать внешнему миру через ваше приложение.
Например, если мы пишем приложение для управления задачами, экземпляры
ресурсов будут следующие:
Конкретный пользователь
Конкретная задача
Список задач

URI ресурса

Когда вы разрабатываете RESTful сервисы, вы должны сосредоточить свое внимание


на ресурсах приложения. Способ, которым мы идентифицируем ресурс для
предоставления, состоит в том, чтобы назначить ему URI — универсальный
идентификатор ресурса. Например:

Методы http

● GET: получить подробную информацию о ресурсе


● POST: создать или обновить существующий ресурс, неидемпотентная
операция, побочные эффекты
● PUT: обновить существующий ресурс, идемпотентная операция
● DELETE: Удалить ресурс
● PATCH: обновить ресурс частично
● TRACE: предоставляет способ проверить, что получает сервер. Он просто
возвращает то, что было отправлено.
● OPTIONS: позволяет клиенту получить информацию о методах запроса,
поддерживаемых службой. Соответствующий заголовок ответа разрешен с
помощью поддерживаемых методов. Также используется в CORS в качестве
предполетного запроса для информирования сервера о фактическом методе
запроса и запроса пользовательских заголовков.
● HEAD: возвращает только заголовки ответов.
● CONNECT: используется браузером, когда он знает, что разговаривает с
прокси-сервером, и окончательный URI начинается с https://. Цель CONNECT
состоит в том, чтобы разрешить end-to-end зашифрованный сеанс TLS, поэтому
данные нечитаемы для прокси-сервера.

Статусы http

● 1xx - информационное
● 2xx - успешное
● 3xx - перенаправление
● 4xx - ошибка клиента
● 5xx - ошибка сервера

Принципы

● pure data
● без состояния
● многоуровневая архитектура
● единый унифицированный интерфейс
● кешируемая архитектура
● удобное представление данных

REST и Ресурсы

Важно отметить, что с REST вам нужно думать о приложении с точки зрения ресурсов:
Определите, какие ресурсы вы хотите открыть для внешнего мира
Используйте глаголы, уже определенные протоколом HTTP, для выполнения операций
с этими ресурсами.

Вот как обычно реализуется служба REST:

Формат обмена данными: здесь нет никаких ограничений. JSON — очень популярный
формат, хотя можно использовать и другие, такие как XML
Транспорт: всегда HTTP. REST полностью построен на основе HTTP.
Определение сервиса: не существует стандарта для этого, а REST является гибким.
Это может быть недостатком в некоторых сценариях, поскольку потребляющему
приложению может быть необходимо понимать форматы запросов и ответов. Однако
широко используются такие языки определения веб-приложений, как WADL (Web
Application Definition Language) и Swagger.

процесс vs поток

Процессы и потоки связаны друг с другом, но при этом имеют существенные различия.

Процесс — экземпляр программы во время выполнения, независимый объект,


которому выделены системные ресурсы (например, процессорное время и память).
Каждый процесс выполняется в отдельном адресном пространстве: один процесс не
может получить доступ к переменным и структурам данных другого. Если процесс
хочет получить доступ к чужим ресурсам, необходимо использовать межпроцессное
взаимодействие. Это могут быть конвейеры, файлы, каналы связи между
компьютерами и многое другое.

Поток использует то же самое пространства стека, что и процесс, а множество потоков


совместно используют данные своих состояний. Как правило, каждый поток может
работать (читать и писать) с одной и той же областью памяти, в отличие от процессов,
которые не могут просто так получить доступ к памяти другого процесса. У каждого
потока есть собственные регистры и собственный стек, но другие потоки могут их
использовать.

Поток — определенный способ выполнения процесса. Когда один поток изменяет


ресурс процесса, это изменение сразу же становится видно другим потокам этого
процесса.
Что происходит при отправке запроса в браузер
Сначала браузер понимает, что нужно сделать http запрос на сервер, обслуживающий
домен yandex.ru.

Потом браузер пытается узнать ip адрес, сначала в ряде специфических мест (файл
hosts, кеш роутера и прочее), если ничего не помогает - идет обращение в dns.

Когда ip адрес известен, можно делать http запрос, который шлется через tcp/ip.

Они пожимают руки и открывают соединение.


Потом отправленный запрос принимает веб-сервер с ip, который мы узнали.
Руководствуясь внутренней логикой, он передает запрос бекенду, который должен его
обработать.

Бэкенд формирует ответ, передает его веб-серверу, который шлет его браузеру
пакетами.
Соединение закрывается.
А браузер уже интерпретирует ответ исходя из статуса ответа, его типа, содержимого и
прочего.

Mysql vs Postqresql

Если коротко: практически всем.


- Намного лучше оптимизатор, перед которым не нужно плясать с бубном как с MySQL.
- Намного более продвинутый язык - pl/PgSQL + возможность использовать Java
- Схемы
- Продвинутые констрейны, при желании можно например проверять попадание точки
на карте в заданную область.
- Rule instead/Also
- Массивы
- Множество продвинутых типов данных как например hstore или jsonb с возможностью
использования индексов
- Именованные Prepared
- крайне продвинутый FTS, который можно гибко настраивать и исползовать для
многих разных целей (все же прямой поиск по текстам я предпочитаю выполнять при
помощи sphinx/elastic)

Это все - первое, что пришло в голову. Кроме на Postgre можно легко и просто
реализовать почти всю или всю логику и выбирать наружу только данные ужо.

Если MySQL хватает - хорошо. Если же нужны сложные связи данных, всякие
навороченные штуки, то переход с my На postgre довольно приятен 8)

UPD: ах да, еще рекурсивные запросы, очень много раз жалел что в MySQL их нет
Масштабирование

Вертикальное масштабирование
Увеличение производительности каждого компонента системы с целью повышения
общей производительности. Добавление памяти, дисков, ядер и тд

Горизонтальное масштабирование

Разбиение системы на более мелкие структурные компоненты и разнесение их по


отдельным интстансам.

Партицирование

Секционирование (англ. partitioning) — разделение хранимых объектов баз данных


(таких как таблиц, индексов, материализованных представлений) на отдельные части с
раздельными параметрами физического хранения. Используется в целях повышения
управляемости, производительности и доступности для больших баз данных.

Возможные критерии разделения данных, используемые при секционировании — по


предопределённым диапазонам значений, по спискам значений, при помощи значений
хеш-функций; в некоторых случаях используются другие варианты. Под композитными
(составными) критериями разделения понимают последовательно применённые
критерии разных типов.

В отличие от сегментирования (англ. sharding), где каждый сегмент управляется


отдельным экземпляром СУБД, и используются средства координации между ними
(что позволяет распределить базу данных на несколько вычислительных узлов), при
секционировании доступ ко всем секциям осуществляется из единого экземпляра
СУБД (или симметрично из любого экземпляра кластерной СУБД, такого, как Oracle
RAC).

Шардирование

Если упорно гуглить, то выяснится, что между так называемым партиционированием и


так называемым шардингом достаточно размытая граница. Каждый называет все, что
хочет, чем хочет. Одни люди различают горизонтальное партиционирование и шардинг.
Другие говорят, что шардинг — это определенный вид горизонтального
партиционирования.

Единого терминологического стандарта, который был бы одобрен


отцами-основателями и в ISO сертифицирован, я не нашел. Личное внутреннее
убеждение примерно такое: Partitioning в среднем — это «режем базу на куски»
произвольно взятым образом.
● Vertical partitioning — поколоночно. Например, есть гигантская таблица на пару
миллиардов записей в 60 колонок. Вместо того, чтобы держать одну такую
гигантскую таблицу, держим 60 не менее гигантских таблиц по 2 млрд записей
— и это не поколоночная база, а вертикальное партиционирование (как пример
терминологии).
● Horizontal partitioning — режем построчно, может быть, внутри сервера.

Шардирование — это в целом, когда большая таблица в терминах баз или


проколлекция документов, объектов, если у вас не совсем база данных, а document
store, режется именно по объектам. То есть из 2 млрд объектов выбираются куски не
важно, какого размера. Объекты сами по себе внутри каждого объекта не разрезаем на
куски, на отдельные колонки не раскладываем, а именно пачками раскладываем в
разные места.

Теорема CAP
Теорема CAP (известная также как теорема Брюера) — эвристическое утверждение о
том, что в любой реализации распределённых вычислений возможно обеспечить не
более двух из трёх следующих свойств:

согласованность данных (англ. consistency) — во всех вычислительных узлах в


один момент времени данные не противоречат друг другу;
доступность (англ. availability) — любой запрос к распределённой системе
завершается корректным откликом, однако без гарантии, что ответы всех узлов
системы совпадают;
устойчивость к разделению (англ. partition tolerance) — расщепление
распределённой системы на несколько изолированных секций не приводит к
некорректности отклика от каждой из секций.

Как передаются массивы в php


Если не изменяются, то по ссылке, если нет - по значению

Как передаются объекты в php


Важно понимать особенности с передачей объектов. Вы могли читать, что в php все
объекты передаются по ссылке.
Это было верно до php5, но сейчас передается только идентификатор объекта.
Где хранить события
Важные - в реляционных базах или базах, поддерживающих ACID, неважные в
key-value хранилищах в памяти

Что делать, если одни события нужно обрабатывать более


важно
Очередь с приоритетом

Как спроектировать если много поставщиков событий и


один обработчик
Очередь

Иерархия исключений
Throwable
--- Error
--------ArithmeticError
--------AssertionError
--------CompileError
--------TypeError
----Exception

OOD

Объектно-ориентированный дизайн (ООД) — это методика проектирования, точка, в


которой во время работы над продуктом сходятся все члены команды: дизайнеры,
проектировщики, разработчики, SEO-специалисты и копирайтеры. В этом случае под
дизайном я понимаю не столько внешний вид системы, сколько то, как она работает.

Принципы: DRY, KISS, SOLID, OOP

Этапы:

● Выявляем объекты
● Определяем параметры объекта и связи
● Определить варианты и способы взаимодействия
● Определяем свойства параметров
OOP vs OOD vs OOA

Объектно-ориентированный анализ - это методология, при которой требования к


системе воспринимаются с точки зрения классов и объектов, выявленных в
предметной области.

Объектно-ориентированное проектирование - это методология проектирования,


соединяющая в себе процесс объектной декомпозиции и приемы представления
логической и физической, а также статической и динамической моделей
проектируемой системы.

Объектно-ориентированное программирование - это методология программирования,


основанная на представлении программы в виде совокупности объектов, каждый из
которых является экземпляром определенного класса, а классы образуют иерархию
наследования.

OOA - Объектно-ориентированный анализ.

Менеджер привел заказчика. Заказчик хочет сферического коня в вакууме.


Руководитель берет тимлида, ведущего программиста и все трое со всех сил
стараются понять, чего же он хочет. Далее уже без заказчика гл. программист сидит и
долго думает, что это будет за зверь, как же этот конь будет выглядеть, какие части (не
путать с классами) будут в проекте.

После выделения частей коня решено, что он будет состоять из трех частей:
сервер-служба, гуй-клиент-настройщик, веб-морда.

OOD - Объектно-ориентированный дизайн.

Тимлиду поручено сделать сервер и он начинает думать в сторону того, как будет
устроен сервер, рисует одному ему понятные стрелочки и продумывает очень
иерархию частей этого сервера и их взаимодействие.

OOP - Объектно-ориентированное программирование.

Сижу я. Решаю, что "ConectionPool <>------ ClientProcessor" (агрегирование), при этом


ClientProcessor будет наследником того-то и того-то... Рисую UML, показываю тимлиду.
Кивает - делаю.
чем отличается фреймворк от библиотеки

Кто кого вызывает.


Ваш код вызывает библиотеки, а код фреймворка вызывает ваш код

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

Зачем нужно?

● Независимость от фреймворка
● Тестируемость
● Независимость от UI
● Независимость от базы данных
● Независимость от какого-либо внешнего сервиса

всё это про бизнес логику

Правило Зависимостей
Зависимости в исходном коде могут указывать только во внутрь. Ничто из внутреннего
круга не может знать что-либо о внешнем круге, ничто из внутреннего круга не может
указывать на внешний круг. Это касается функций, классов, переменных и даже
структур данных.

Сущности
Сущности определяются бизнес-правилами предприятия. Сущность может быть
объектом с методами или она может представлять собой набор структур данных и
функций. Они инкапсулируют наиболее общие высокоуровневые правила. Наименее
вероятно, что они изменятся при каких-либо внешних изменениях. Например, они не
должны быть затронуты при изменении навигации по страницам или правил
безопасности. Внешние изменения не должны влиять на слой сущностей.

Сценарии
В этом слое реализуется специфика бизнес-правил. Он инкапсулирует и реализует все
случаи использования системы. Эти сценарии реализуют поток данных в и из слоя
Cущностей для реализации бизнес-правил. Мы не ожидаем изменения в этом слое,
влияющих на Cущности. Мы также не ожидаем, что это слой может быть затронут
внешними изменениями. Мы, однако, ожидаем, что изменения в работе приложения
повлияет на Cценарии. Если будут какие-либо изменения в поведении приложения, то
они несомненно затронут код в данном слое.

Интерфейс-Адаптеры
Программное обеспечение в этом слое представляет собой набор адаптеров, которые
преобразуют данные из формата наиболее удобным для Сценариев и Сущностей, в
формат наиболее удобный для дальнейшего использования, например в БД. Именно
это слой, например, будет полностью содержать архитектуру MVC. Модели являются
скорее всего структурами данных, которые передаются от контроллеров к Сценариям,
а затем обратно из Сценариев к Представлениям.

Точно так же, данные преобразуются, в этом слое, из формы наиболее удобным для
Сценариев и Сущностей, в форму, наиболее удобной для постоянного хранения,
например в базе данных. Код, находящийся внутри этого круга не должен знать
что-либо о БД. Если БД — это SQL база данных, то любые SQL-инструкции не должны
быть использованы на этом уровне.

Фреймворки и драйверы
Наружный слой обычно состоит из фреймворков, БД, UI и т.д. Как правило, в этом слое
не пишется много кода, за исключением кода, который общается с внутренними
кругами. Это слой скопления деталей. Интернет — деталь, БД — деталь, мы держим
эти штуки снаружи для уменьшения их влияния.

Пересечение границ
Контроллеры и Представления взаимодействуют со Сценариями из следующего слоя.
Обратите снимание на поток управления. Она начинается в Контроллере, движется
через Сценарий, а затем завершает выполнение в Представлении. Обратите внимание
на зависимости в исходном коде. Каждая из них указывает внутрь к Сценарию.

Например, предположим, что из Сценария нужно обратиться к Представлению.


Однако, этот вызов обязан быть не прямым, чтобы не нарушать Правило
Зависимостей — внутренний круг не знает ничего о внешнем. Таким образом
Сценарий вызывает интерфейс (на схеме показан как Выходной Порт) во внутреннем
круге, а Представление из внешнего круга реализует его.

Та же самая техника используется, чтобы пересечь все границы в архитектуре. Мы


воспользуемся преимуществами динамического полиморфизма для создания
зависимостей в исходном коде так, чтобы поток управления соответствовал Правилу
Зависимостей.

Как данные пересекает границы


Обычно данные, которые пересекают границы — это просто структуры данных. Вы
можете использовать базовые структуры или, если хотите, Data Transfer Objects (DTO
— один из шаблонов проектирования, используется для передачи данных между
подсистемами приложения). Или данные могут быть просто аргументами вызова
функций. Поэтому передача данных через границу всегда должна быть в формате
удобном для внутреннего круга.

Гексоганальная архитектура

Является дополнением чистой архитектуры. Чистая архитектура про слои и


пересечения границ. Но в ней не говорится о том, как должны общаться отдельные
подсистемы на своём слое. Например, на инфраструктурном уровне у нас gui и бд, но
это не значит, что они должны общаться друг с другом напрямую. Необходимо
реализовывать так называемые порты и адаптеры. То есть продумать некое API с
интерфейсом и реализацией. Интерфейс у нас должен быть в подсистеме, которая
что-то использует, а реализация в подсистеме, которая использует.

Когда чего использовать

Clean Architecture хорошо работает в паре с Bounded Context. Разные контексты могут
представлять собой разные подсистемы. Простые контексты лучше реализовывать с
помощью простого CRUD. Для контекстов с асимметричной нагрузкой хорошо
подойдет CQRS. Для подсистем, требующих Audit Log'а есть смысл использовать
Event Sourcing. Для нагруженных на чтение и запись подсистемах с ограничениями по
пропускной способности и задержкам есть смысл рассмотреть event driven — подход.
На первый взгляд это может показаться неудобным. Например я работал с
CRUD-подсистемой и мне пришла задача из CQRS-подсистемы. Придется некоторе
время смотреть на все эти Command и Query как на новые ворота. Альтернатива —
проектировать систему в едином стиле — недальновидна. Архитектура — это набор
инструментов, а каждый инструмент подходит для решения конкретной задачи.

Алгоритмы сортировки

Сортировка пузырьком

Сортировка пузырьком — один из самых известных алгоритмов сортировки. Здесь


нужно последовательно сравнивать значения соседних элементов и менять числа
местами, если предыдущее оказывается больше последующего. Таким образом
элементы с большими значениями оказываются в конце списка, а с меньшими
остаются в начале.

Сортировка перемешиванием
Шейкерная сортировка отличается от пузырьковой тем, что она двунаправленная:
алгоритм перемещается не строго слева направо, а сначала слева направо, затем
справа налево.
Сортировка расчёской
Сортировка расчёской — улучшение сортировки пузырьком. Её идея состоит в том,
чтобы «устранить» элементы с небольшими значения в конце массива, которые
замедляют работу алгоритма. Если при пузырьковой и шейкерной сортировках при
переборе массива сравниваются соседние элементы, то при «расчёсывании» сначала
берётся достаточно большое расстояние между сравниваемыми значениями, а потом
оно сужается вплоть до минимального.
Сначала расстояние между элементами будет равняться размеру массива,
поделённому на 1,247; на каждом последующем шаге расстояние будет снова
делиться на фактор уменьшения — и так до окончания работы алгоритма.

Сортировка вставками
При сортировке вставками массив постепенно перебирается слева направо. При этом
каждый последующий элемент размещается так, чтобы он оказался между
ближайшими элементами с минимальным и максимальным значением.
Сортировка выбором
Сначала нужно рассмотреть подмножество массива и найти в нём максимум (или
минимум). Затем выбранное значение меняют местами со значением первого
неотсортированного элемента. Этот шаг нужно повторять до тех пор, пока в массиве
не закончатся неотсортированные подмассивы.

Быстрая сортировка
Этот алгоритм состоит из трёх шагов. Сначала из массива нужно выбрать один
элемент — его обычно называют опорным. Затем другие элементы в массиве
перераспределяют так, чтобы элементы меньше опорного оказались до него, а
большие или равные — после. А дальше рекурсивно применяют первые два шага к
подмассивам справа и слева от опорного значения.
Сортировка слиянием
Сортировка слиянием пригодится для таких структур данных, в которых доступ к
элементам осуществляется последовательно (например, для потоков). Здесь массив
разбивается на две примерно равные части и каждая из них сортируется по
отдельности. Затем два отсортированных подмассива сливаются в один.

Пирамидальная сортировка
При этой сортировке сначала строится пирамида из элементов исходного массива.
Пирамида (или двоичная куча) — это способ представления элементов, при котором от
каждого узла может отходить не больше двух ответвлений. А значение в родительском
узле должно быть больше значений в его двух дочерних узлах.

Пирамидальная сортировка похожа на сортировку выбором, где мы сначала ищем


максимальный элемент, а затем помещаем его в конец. Дальше нужно рекурсивно
повторять ту же операцию для оставшихся элементов.
Алгоритмы поиска

Последовательный поиск
просто перебор O(n)

Индексно-последовательный поиск
ищем по индексной таблице, потом углубляемся в основную

O(N + n/N)

Бинарный поиск
При бинарном поиске искомый ключ сравнивается с ключом среднего элемента в
массиве. Если они равны, то поиск успешен. В противном случае поиск
осуществляется аналогично в левой или правой частях массива.

Поиск в глубину

Поиск в глубину — обходит область поиска, используя LIFO-стек для определения


следующей вершины.
Преимущества: хорошо работает в глубоких графах, эффективен по памяти.
Недостатки: есть вероятность зацикливания.
Стратегия поиска в глубину, как и следует из названия, состоит в том, чтобы идти
«вглубь» графа, насколько это возможно. Алгоритм поиска описывается рекурсивно:
перебираем все исходящие из рассматриваемой вершины рёбра. Если ребро ведёт в
вершину, которая не была рассмотрена ранее, то запускаем алгоритм от этой
нерассмотренной вершины, а после возвращаемся и продолжаем перебирать рёбра.
Возврат происходит в том случае, если в рассматриваемой вершине не осталось
рёбер, которые ведут в нерассмотренную вершину. Если после завершения алгоритма
не все вершины были рассмотрены, то необходимо запустить алгоритм от одной из
нерассмотренных вершин

Поиск в ширину

Поиск в ширину обходит область поиска, используя FIFO-очередь для определения


следующей вершины.
Поиск в ширину имеет такое название потому, что в процессе обхода мы идём вширь,
т.е. перед тем как приступить к поиску вершин на расстоянии
выполняется обход вершин на расстоянии
Микросервисы
Архитектура микрослужб представляет собой набор небольших автономных служб.
Каждая служба является самодостаточной и должна реализовывать возможности
одной компании.

● Микрослужбы — это небольшие, независимые и слабо связанные решения.


Создавать и обслуживать их может даже небольшая команда разработчиков.
● Каждая служба является отдельной базой кода, которой может управлять
небольшая команда разработчиков.
● Службы можно развертывать независимо друг от друга. Разработчики могут
обновлять существующую службу без повторной сборки и повторного
развертывания всего приложения.
● Службы отвечают за сохранение собственных данных или внешнего состояния.
В этом состоит отличие от традиционной модели, в которой сохранение данных
обрабатывается на отдельном уровне.
● Службы взаимодействуют между собой с помощью четко определенных
API-интерфейсов. Сведения о внутренней реализации каждой службы скрыты
от других служб.
● Службы не должны совместно использовать один и тот же стек технологий,
библиотеки или платформы.

Помимо самих служб, некоторые компоненты обладают типичной архитектурой


микрослужб:

● Управление и оркестрация Этот компонент отвечает за размещение служб на


узлах, определение сбоев, перераспределение служб между узлами и другие
операции. Как правило, этот компонент является коммерческим продуктом
(например, Kubernetes), а не разрабатываемым по заказу.
● Шлюз API. Шлюз API является точкой входа для клиентов. Вместо того, чтобы
вызывать службы непосредственно, клиенты вызывают шлюз API, который
пересылает вызов соответствующим службам в серверной части.

Юнит тесты Vs функциональные тесты

Модульное тестирование (тестирование отдельных частей продукта, обычно


отдельных функций/методов)
Функциональное тестирование — тестирование некого функционала продукта, при
этом продукт воспринимается как единый «чёрный ящик»

Виды тестов

Блочное (Unit testing) — тестирование одного модуля в изоляции.


Интеграционное (Integration Testing) — тестирование группы взаимодействующих
модулей.
Системное (System Testing) — тестирование системы в целом.

Раннее статическое связывание self

Для обхода используется static:: вместо self::

Анонимные функции

Callable — это специальный псевдотип данных в PHP, означающий «нечто, что может
быть вызвано как функция».

В PHP существует специальный системный класс Closure. Когда вы создаете новую


анонимную функцию, по сути вы неявно создаете объект этого класса.

Объект вполне может быть «функцией», достаточно лишь определить в классе


магический метод __invoke():

Unit of work
Unit of Work - это паттерн определяющий логическую транзакцию т.е. атомарную
синхронизацию изменений в объектах, помещённых в объект UoW с хранилищем
(базой данных).

Основная работа производится в методе commit() который отвечает за вычисление


изменений в сохранённых в UoW объектах и синхронизацию этих изменений с
хранилищем (базой данных).

Data Mapper
Data Mapper — это программная прослойка, разделяющая объект и БД. Его
обязанность — пересылать данные между ними и изолировать их друг от друга. При
использовании Data Mapper'а объекты не нуждаются в знании о существовании БД.
Они не нуждаются в SQL-коде, и (естественно) в информации о структуре БД. Так как
Data Mapper - это разновидность паттерна Mapper, сам объект-Mapper неизвестен
объекту.
Active Record
Схема Active Record — это подход к доступу к данным в базе данных. Таблица базы
данных или представление обёрнуты в классы. Таким образом, объектный экземпляр
привязан к единственной строке в таблице. После создания объекта новая строка
будет добавляться к таблице на сохранение. Любой загруженный объект получает
свою информацию от базы данных. Когда объект обновлён, соответствующая строка в
таблице также будет обновлена. Класс обёртки реализует методы средства доступа
или свойства для каждого столбца в таблице или представлении.
Может быть антипаттерном, если объект умеет себя сохранять и содержать бизнес
логику одновременно.

ORM

ORM — фреймворк для данных. С помощью него описываются сущности и их связи,


определяется то, как сущность отображается на базу данных (как правило в
полуавтоматическом режиме). ORM берет на себя серьёзную часть работы по
генерации SQL-запросов, по извлечению данных и кастингу (преобразование типов
базы данных в типы целевого языка и обратно), по автоматическому извлечению
связей. В итоге получается, что ORM прячет всю работу с базой данных (требуя только
правильного конфигурирования) и сама выполняет все необходимые запросы.

Итератор

iterable ---> array


--> Traversable ---> Iterator
--> IteratorAggregate
--> Generator

Генератор

Генератор позволяет вам писать код, использующий foreach для перебора набора
данных без необходимости создания массива в памяти, что может привести к
превышению лимита памяти, либо потребует довольно много времени для его
создания. Вместо этого, вы можете написать функцию-генератор, которая, по сути,
является обычной функцией, за исключением того, что вместо возврата единственного
значения, генератор может возвращать (yield) столько раз, сколько необходимо для
генерации значений, позволяющих перебрать исходный набор данных.
Главное преимущество генераторов - это их простота. Гораздо меньше шаблонного
кода надо написать, по сравнению с реализацией объекта класса Iterator, и этот код
гораздо более простой и понятный. К примеру, эта функция и класс делают одно и то
же.

Однако за эту простоту, впрочем, приходится платить: генераторы могут быть только
однонаправленными итераторами. Их нельзя перемотать назад после старта
итерации. Это также означает, что один и тот же генератор нельзя использовать
несколько раз: генератор необходимо пересоздавать каждый раз, снова вызвав
функцию генератора.

● ... упрощенные итераторы;


● ... могут возвращать неограниченные объемы данных без
дополнительного потребления памяти;
● ... могут быть агрегированы с помощью делегирования генераторов;
● ... могут быть использованы для реализации многозадачности;

Корутины
Главное, что корутины добавляют к вышеописанной функциональности — это
возможность отправлять значения генератору. Это делает из привычного монолога
генератора полноценный диалог, где вызывающая сторона может также что-то
сообщать генератору.

Стрелочные функции
Стрелочные функции поддерживают те же возможности, что и анонимные функции, за
исключением того, что использование переменных из родительской области всегда
выполняется автоматически.

● Стрелочные функции захватывают переменные по значению автоматически


● Стрелочные функции захватывают переменные по значению автоматически,
даже когда они вложены
● Значения из внешней области видимости не могут быть изменены стрелочными
функциями

За счёт чего была проведена оптимизация php7


оптимизация интрепретатора: переработка внутренних структур данных и работы с
памятью
За счёт чего была проведена оптимизация php7.1
оптимизацию байт-кода

php5.4

короткий синтаксис массива, трейты, callable typehint

php5.5

finnally, генераторы

php 5.6

...$strings

php 7.0
оптимизация, операторы ??, ⇔
Типы скалярных параметров и подсказки (hints) по возвращаемым типам
добавлен новый интерфейс Throwable
Анонимные классы

php 7.1
nullable types, [] = as alternative construct to list() =, void return type.

php 7.2
Оптимизирована работа встроенной функции in_array() с помощью поиска хеша в
перевернутом массиве.
Добавлена возможность перегружать абстрактные функции
использовать type hints с типом данных объекта

php 7.3
Добавление функций array_key_first() и array_key_last(), countable
Поддержка конечных запятых в вызовах функций и методов
php 7.4

Предварительная загрузка
Типизированные свойства классов
Присваивающий оператор объединения с null (??=)
оператор Spread в массивах
В PHP 7.4 появляется ковариантность (порядок от конкретного к общему) и
контравариантность (обратный порядок) для типов возвращаемых данных и
параметров.

php 8

JIT
Аннотации/Атрибуты (Attributes)
Именованные параметры
Оператор безопасного null (Nullsafe operator)
$country = $session?->user?->getAddress()?->country;
Оператор выбора match
Адекватное приведение строки в число
Constructor Property Promotion
Объединения типов, тип mixed

PSR
● 1 - code style
● 3 - Logger Interface
● 4 - Autoloading Standard
● 6 - Caching Interface
● 7 - HTTP Message Interface
● 11 - Container Interface\
● 12 - improve code style
● 13 - Hypermedia Links
● 14 - Event Dispatcher
● 15 - HTTP Handlers
● 16 - Simple Cache
● 17 - HTTP Factories
● 18 - HTTP Client

https://github.com/php-fig
ES6
● arrows
● classes
● enhanced object literals
● template strings
● destructuring
● default + rest + spread
● let + const
● iterators + for..of
● generators
● unicode
● modules
● module loaders
● map + set + weakmap + weakset
● proxies
● symbols
● subclassable built-ins
● promises
● math + number + string + array + object APIs
● binary and octal literals
● reflect api
● tail calls

ES7
● Array.prototype.includes()
● Exponentiation operator

ES8

● Async Functions
● Shared memory and atomics
● Object.values/Object.entries
● String padding
● Object.getOwnPropertyDescriptors()
● Trailing commas in function parameter lists and calls

ES9
● Asynchronous Iteration
● Rest/Spread Properties
● RegExp named capture groups
● RegExp Unicode Property Escapes
● RegExp Lookbehind Assertions
● s (dotAll) flag for regular expressions
● Promise.prototype.finally()
● Template Literal Revision

ES10
● String.matchAll()
● Array.flat() & Array.flatMap()
● Dynamic Import
● Object.fromEntries()
● TrimStart() and TrimEnd()
● Symbol.prototype.description()
● Optional Catch Binding
● Well Formed JSON.stringify()
● Array Sort Stability
● Enhanced toString()
● Standardized “globalThis” Object

ES11
● Optional Chaining
● Nullish Coalescing
● Private Fields
● Static Fields
● Top Level Await
● Promise.allSettled
● Dynamic Import
● MatchAll
● globalThis
● BigInt

ES12
● String replaceAll()
● Приватные методы
● Приватные аксессоры
● WeakRef
● Финализаторы
● Promise.any() и AggregateError
● Оператор логического присваивания
● Оператор логического присваивания с ||
● Оператор логического присваивания с ??

Типы данных

Скалярные типы:

● bool
● int
● float (иногда встречается название double что для php не имеет разницы)
● string

Смешанные типы:
● array
● object
● callable
● iterable

Специальные типы:

● resource
● null

Сравнение объектов

При использовании оператора сравнения (==), свойства объектов просто сравниваются


друг с другом, а именно: два объекта равны, если они имеют одинаковые атрибуты и
значения (значения сравниваются через ==) и являются экземплярами одного и того же
класса.

С другой стороны, при использовании оператора идентичности (===), переменные,


содержащие объекты, считаются идентичными только тогда, когда они ссылаются на
один и тот же экземпляр одного и того же класса.

MyISAM vs Innodb

Описание MyISAM InnoDB


Транзакционный движок?Транзакция (Transaction) —

блок операторов SQL , который в случае ошибки в

одном запросе, возвращается к предыдущему Нет Да

состоянию (Rollback), и только в случае выполнения

всех запросов подтверждается (Commit)

Поддержка внешних ключейВнешние ключи — это

способ связать записи в двух таблицах по

определенным полям так, что при обновлении поля в

родительской автоматически происходит


Нет Да
определенное изменение поля в дочерней (дочернюю

и родительскую выбираешь при создании ключа;

точнее, создаешь ключ в дочерней, который ссылается

на родительскую).

Блокировка.Блокировка на уровне строк, т.е. если Блокировк

процессу нужно обновить строку в таблице, то он а на Блокировка на

блокирует только эту строку, позволяя другим уровне уровне строк

обновлять другие строки параллельно таблиц

Одновременные запросы к разным частям таблицы. Медленнее Быстрее

При смешанной нагрузке в таблице


Медленнее Быстрее
(select/update/delete/insert)

Медленнее,

ибо есть
Операция Insert Быстрее
оверхед на

транзакцию, но
это цена

надежности

Работает Работает
Если преобладают операции чтения (SELECT)
быстрее медленнее

DeadlockDeadlock — ситуация в многозадачной среде

или СУБД, при которой несколько процессов находятся Не


Возможны.
в состоянии бесконечного ожидания ресурсов, возникают

захваченных самими этими процессами.

Нет (доступен

начиная с
Поддержка полнотекстового поиска Да
версии MySQL

5.6.4)

Запрос Count(*) Быстрее Медленнее

Поддержка mysqlhotcopyУтилита mysqlhotcopy

представляет собой Perl-сценарий, использующий

SQL-команды LOCK TABLES, FLUSH TABLES и Да Нет

Unix-утилиты cp или scp для быстрого получения

резервной копии базы данных.

Данные при

Каждой настройках по

таблице умолчанию
Файловое хранение таблиц
отдельный хранятся в

файл больших

совместно
используемых

файлах

Бинарное копировании таблиц?Табличные файлы

можно перемещать между компьютерами разных


Да Нет
архитектур и разными операционными системами без

всякого преобразования.

Размер таблиц в БД Меньше Больше

Крашится По логам

Поведение в случае сбоя вся можно все

таблица восстановить

В случае хранения «логов» и подобного Лучше Хуже

trunk base development


● Короткоживущие ветки. У нас любая ветка, которая создается (кроме
мастера), живет не больше двух дней. Два дня и все, это уже не Trunk и все
печально. Поэтому все ветки, кроме мастера, например, ветка релизная или для
фичи живет не больше двух дней.
● Feature Flags и Branch By Abstraction. Я про это расскажу чуть позже.
● Continuous Code Review.
● И основная идея в том, что у нас теперь и мастер всегда готов к деплою, даже
если в нем есть недописанные фичи. Он всегда – release ready и вообще не
важно, что в нем.

github flow

● Создайте ветвь
● Фиксируйте изменения
● Откройте запрос на слияние
● Проверьте и обсудите код
● Проверьте в бою
● Вливайте

В чём отличие от GitFlow?

В GitFlow у вас есть дополнительная ветвь develop куда сливаются все


разрабатываемые в текущий момент ветви. develop необходимо "стабилизировать"
перед релизом, что часто приводит либо к переносу релиза, либо "релизу с
замечаниями".

В чём отличие от GitLab Flow?

В GitLab Flow вы сначала вливаете ветвь в основной ствол и лишь потом


разворачиваете в тестовом, боевом и других окружениях. Если релиз окажется
проблемным и его потребуется откатить, то потребуется порой весьма проблемный
"reverse merge" либо "стабилизация" ствола, как в случае GitFlow.
GitLab Flow

GitFlow

SemVer

Учитывая номер версии МАЖОРНАЯ.МИНОРНАЯ.ПАТЧ, следует увеличивать:


● МАЖОРНУЮ версию, когда сделаны обратно несовместимые изменения API.
● МИНОРНУЮ версию, когда вы добавляете новую функциональность, не
нарушая обратной совместимости.
● ПАТЧ-версию, когда вы делаете обратно совместимые исправления.
● Дополнительные обозначения для предрелизных и билд-метаданных возможны
как дополнения к МАЖОРНАЯ.МИНОРНАЯ.ПАТЧ формату.

Более полное описание:

● ПО, использующее Семантическое Версионирование, должно объявить


публичный API. Этот API может быть объявлен самим кодом или существовать
строго в документации. Как бы ни было это сделано, он должен быть точным и
исчерпывающим.
● Обычный номер версии ДОЛЖЕН иметь формат X.Y.Z, где X, Y и Z —
неотрицательные целые числа и НЕ ДОЛЖНЫ начинаться с нуля. X —
мажорная версия, Y — минорная версия и Z — патч-версия. Каждый элемент
ДОЛЖЕН увеличиваться численно. Например: 1.9.0 ->1.10.0 -> 1.11.0.
● После релиза новой версии пакета содержание этой версии НЕ ДОЛЖНО быть
модифицировано. Любые изменения ДОЛЖНЫ быть выпущены как новая
версия.
● Мажорная версия ноль (0.y.z) предназначена для начальной разработки. Всё
может измениться в любой момент. Публичный API не должен рассматриваться
как стабильный.
● Версия 1.0.0 определяет публичный API. После этого релиза номера версий
увеличиваются в зависимости от того, как изменяется публичный API.
● Патч-версия Z (x.y.Z | x > 0) ДОЛЖНА быть увеличена только если содержит
обратно совместимые баг-фиксы. Определение баг-фикс означает внутренние
изменения, которые исправляют некорректное поведение.
● Минорная версия (x.Y.z | x > 0) ДОЛЖНА быть увеличена, если в публичном API
представлена новая обратно совместимая функциональность. Версия ДОЛЖНА
быть увеличена, если какая-либо функциональность публичного API помечена
как устаревшая (deprecated). Версия МОЖЕТ быть увеличена в случае
реализации новой функциональности или существенного усовершенствования
в приватном коде. Версия МОЖЕТ включать в себя изменения, характерные
для патчей. Патч-версия ДОЛЖНА быть обнулена, когда увеличивается
минорная версия.
● Мажорная версия X (X.y.z | X > 0) ДОЛЖНА быть увеличена, если в публичном
API представлены какие-либо обратно несовместимые изменения. Она МОЖЕТ
включать в себя изменения, характерные для уровня минорных версий и
патчей. Когда увеличивается мажорная версия, минорная и патч-версия
ДОЛЖНЫ быть обнулены.
● Предрелизная версия МОЖЕТ быть обозначена добавлением дефиса и серией
разделённых точкой идентификаторов, следующих сразу за патч-версией.
Идентификаторы ДОЛЖНЫ содержать только ASCII буквенно-цифровые
символы и дефис [0-9A-Za-z-]. Идентификаторы НЕ ДОЛЖНЫ быть пустыми.
Числовые идентификаторы НЕ ДОЛЖНЫ начинаться с нуля. Предрелизные
версии имеют более низкий приоритет, чем соответствующая релизная версия.
Предрелизная версия указывает на то, что эта версия не стабильна и может не
удовлетворять требованиям совместимости, обозначенными соответствующей
нормальной версией. Примеры: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7,
1.0.0-x.7.z.92.
● Сборочные метаданные МОГУТ быть обозначены добавлением знака плюс и
ряда разделённых точкой идентификаторов, следующих сразу за патчем или
предрелизной версией. Идентификаторы ДОЛЖНЫ содержать только ASCII
буквенно-цифровые символы и дефис [0-9A-Za-z-]. Идентификаторы НЕ
ДОЛЖНЫ быть пустыми. Сборочные метаданные СЛЕДУЕТ игнорировать, когда
определяется старшинство версий. Поэтому два пакета с одинаковой версией,
но разными сборочными метаданными, рассматриваются как одна и та же
версия. Примеры: 1.0.0-alpha+001, 1.0.0+20130313144700,
1.0.0-beta+exp.sha.5114f85.
● Приоритет определяет, как версии соотносятся друг с другом, когда
упорядочиваются. Приоритет версий ДОЛЖЕН рассчитываться путём
разделения номеров версий на мажорную, минорную, патч и предрелизные
идентификаторы. Именно в такой последовательности (сборочные метаданные
не фигурируют в расчёте). Приоритет определяется по первому отличию при
сравнении каждого из этих идентификаторов слева направо: Мажорная,
минорная и патч-версия всегда сравниваются численно. Пример: 1.0.0 < 2.0.0 <
2.1.0 < 2.1.1. Когда мажорная, минорная и патч-версия равны, предрелизная
версия имеет более низкий приоритет, чем нормальная версия. Пример:
1.0.0-alpha < 1.0.0. Приоритет двух предрелизных версий с одинаковыми
мажорной, минорной и патч-версией ДОЛЖНЫ быть определены сравнением
каждого разделённого точкой идентификатора слева направо до тех пор, пока
различие не будет найдено следующим образом: идентификаторы, состоящие
только из цифр, сравниваются численно; буквенные идентификаторы или
дефисы сравниваются лексически в ASCII-порядке. Численные
идентификаторы всегда имеют низший приоритет, чем символьные. Больший
набор предрелизных символов имеет больший приоритет, чем меньший набор,
если сравниваемые идентификаторы равны. Пример: 1.0.0-alpha < 1.0.0-alpha.1
< 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.

Переопределение констант в интерфейсах

Нельзя, будет ошибка.

Переопределение констант в абстрактных классах

Можно, ошибки не будет


SOA vs MSA

SOA
В его основе лежат несколько основных идей – переиспользование сервисов и
корпоративная шина. Разработчики стремятся разбить систему на сервисы таким
образом, чтобы их можно было использовать повторно. Взаимодействие и
маршрутизация осуществляется через корпоративную шину ESB.

Состав:

● Шина(ESB): в случае взаимодействия сложных событий действует как


посредник и управляет различными рутинными операциями, такими как
передача сообщений и координация вызовов.
● Инфраструктурные сервисы (infrastructure services): группа легко
переиспользуемых сервисов, таких как аутентификация/авторизация, отправка
смс и прочее.
● Прикладные сервисы (application services): не могут быть
переиспользованны под разные задачи, так как ограничены определенным
прикладным контекстом, но их можно встраивать в более высокоуровневые
сервисы.
● Сервисы предприятия (Enterprise services): эти сервисы отвечают за
реализацию крупных частей бизнес процессов компании, они потребляют более
низкоуровневые сервисы.
● API: по сути это бэкенды, предоставляющие API, доступное в интернет, для
сайтов и мобильных приложений компании. Они взаимодействуют с ESB и
раскрывают функциональность для конечных потребителей.

MSA
Микросервисы в отличие от SOA, наоборот, избегают повторного использования,
применяя философию - предпочтительнее дублирование, а не зависимость от других
сервисов. Повторное использование предполагает связанность, а архитектура
микросервисов в значительной степени старается ее избегать. Это достигается за счет
разбиения системы на сервисы по ограниченным контекстам (бизнес областям).

● В отличие от SOA каждый сервис обладает всеми необходимыми для


функционирования частями – имеет свою собственную базу данных и
существует как независимый процесс. Такая архитектура делает каждый сервис
физически разделенным, самодостаточным, что ведет с технической точки
зрения к архитектуре без разделения ресурсов.
● Сервисы раскрываются для потребителей также через слой API, но его
стараются проектировать с полным отсутствием какой-либо логики. Это
фактически просто проксирование API сервисов во вне.
● Взаимодействие между сервисами сводится к обмену данными, используя
брокер сообщений. Именно к обмену данными, а не вызову методов из других
сервисов.

Модели OSI

● 1 уровень. Физический (physical). Единицей нагрузки (PDU) здесь является


бит. Кроме единиц и нулей физический уровень не знает ничего. На этом уровне
работают провода, патч панели, сетевые концентраторы (хабы, которые сейчас
уже сложно найти в привычных нам сетях), сетевые адаптеры. Именно сетевые
адаптеры и ничего более из компьютера. Сам сетевой адаптер принимает
последовательность бит и передает её дальше.
● 2 уровень. Канальный (data link). PDU - кадр (frame). На этом уровне
появляется адресация. Адресом является MAC адрес. Канальный уровень
ответственен за доставку кадров адресату и их целостность. В привычных нам
сетях на канальном уровне работает протокол ARP. Адресация второго уровня
работает только в пределах одного сетевого сегмента и ничего не знает о
маршрутизации - этим занимается вышестоящий уровень. Соответственно,
устройства, работающие на L2 - коммутаторы, мосты и драйвер сетевого
адаптера.
● 3 уровень. Сетевой (network). PDU пакет (packet). Наиболее
распространенным протоколом (дальше не буду говорить про “наиболее
распространенный” - статья для новичков и с экзотикой они, как правило, не
сталкиваются) тут является IP. Адресация происходит по IP-адресам, которые
состоят из 32 битов. Протокол маршрутизируемый, то есть пакет способен
попасть в любую часть сети через какое-то количество маршрутизаторов. На L3
работают маршрутизаторы.
● 4 уровень. Транспортный (transport). PDU сегмент (segment)/датаграмма
(datagram). На этом уровне появляются понятия портов. Тут трудятся TCP и
UDP. Протоколы этого уровня отвечают за прямую связь между приложениями и
за надежность доставки информации. Например, TCP умеет запрашивать
повтор передачи данных в случае, если данные приняты неверно или не все.
Так же TCP может менять скорость передачи данных, если сторона приема не
успевает принять всё (TCP Window Size).

Следующие уровни “правильно” реализованы лишь в RFC. На практике же,


протоколы описанные на следующих уровнях работают одновременно на
нескольких уровнях модели OSI, поэтому нет четкого разделения на сеансовый
и представительский уровни. В связи с этим в настоящее время основным
используемым стеком является TCP/IP, о котором поговорим чуть ниже.

● 5 уровень. Сеансовый (session). PDU данные (data). Управляет сеансом


связи, обменом информации, правами. Протоколы - L2TP, PPTP.
● 6 уровень. Представительский (presentation). PDU данные (data).
Преставление и шифрование данных. JPEG, ASCII, MPEG.
● 7 уровень. Прикладной (application). PDU данные (data). Самый
многочисленный и разнообразный уровень. На нем выполняются все
высокоуровненвые протоколы. Такие как POP, SMTP, RDP, HTTP и т.д.
Протоколы здесь не должны задумываться о маршрутизации или гарантии
доставки информации - этим занимаются нижестоящие уровни. На 7 уровне
необходима лишь реализации конкретных действий, например получение
html-кода или email-сообщения конкретному адресату.

Websocket или WebRTC

● WebRTC предназначен для высокопроизводительной, высококачественной


передачи видео, аудио и произвольных данных. Другими словами, для
приложений точно так же, как вы описываете.
● Приложениям WebRTC требуется сервис, с помощью которого они могут
обмениваться метаданными сети и мультимедиа - процесс, известный как
сигнализация. Однако, как только происходит передача сигналов, видео / аудио
/ данные передаются напрямую между клиентами, что позволяет избежать
затрат на производительность потоковой передачи через промежуточный
сервер.
● WebSocket, с другой стороны, предназначен для двунаправленной связи между
клиентом и сервером. Потоковое аудио и видео можно передавать через
WebSocket (см., Например, здесь ), но технология и API-интерфейсы не
предназначены для эффективной и надежной потоковой передачи, как это
делает WebRTC.
● Как уже говорилось в других ответах, WebSocket может использоваться для
сигнализации.

WebRTC

Web Real-Time Communication (WebRTC) это не один протокол, это целая коллекция
стандартов, протоколов и JavaScript API, которые все вместе обеспечивают
peer-to-peer видео-аудио коммуникации в реальном времени, а также могут быть
использованы для передачи любых бинарных данных. Обычно пирами выступают
браузеры, но это может быть и мобильное приложение, например. Для того чтобы
организовать p2p общение между клиентами требуется поддержка браузером
различных видов кодирования видео и аудио, поддержка множества сетевых
протоколов, обеспечение взаимодействия железа с браузером (через слои ОС):
вебкамер, звуковых карт. Вся эта мешанина технологий скрыта за абстракцией
JavaScript API для удобства разработчика.

WebSocket

Веб-сокеты (Web Sockets) — это передовая технология, которая позволяет создавать


интерактивное соединение между клиентом (браузером) и сервером для обмена
сообщениями в режиме реального времени. Веб-сокеты, в отличие от HTTP, позволяют
работать с двунаправленным потоком данных, что делает эту технологию совершенно
уникальной. Давайте разберемся, как работает эта технология и чем она отличается от
HTTP.

Сравнение UDP и TCP

TCP — ориентированный на соединение протокол, что означает необходимость


«рукопожатия» для установки соединения между двумя хостами. Как только
соединение установлено, пользователи могут отправлять данные в обоих
направлениях.

● Надёжность — TCP управляет подтверждением, повторной передачей и


тайм-аутом сообщений. Производятся многочисленные попытки доставить
сообщение. Если оно потеряется на пути, сервер вновь запросит потерянную
часть. В TCP нет ни пропавших данных, ни (в случае многочисленных
тайм-аутов) разорванных соединений.
● Упорядоченность — если два сообщения последовательно отправлены,
первое сообщение достигнет приложения-получателя первым. Если участки
данных прибывают в неверном порядке, TCP отправляет неупорядоченные
данные в буфер до тех пор, пока все данные не могут быть упорядочены и
переданы приложению.
● Тяжеловесность — TCP необходимо три пакета для установки
сокет-соединения перед тем, как отправить данные. TCP следит за
надёжностью и перегрузками.
● Потоковость — данные читаются как поток байтов, не передается никаких
особых обозначений для границ сообщения или сегментов.

UDP — более простой, основанный на сообщениях протокол без установления


соединения. Протоколы такого типа не устанавливают выделенного соединения между
двумя хостами. Связь достигается путём передачи информации в одном направлении
от источника к получателю без проверки готовности или состояния получателя. В
приложениях для голосовой связи через интернет-протокол (Voice over IP, TCP/IP) UDP
имеет преимущество над TCP, в котором любое «рукопожатие» помешало бы хорошей
голосовой связи. В VoIP считается, что конечные пользователи в реальном времени
предоставят любое необходимое подтверждение о получении сообщения.

● Ненадёжный — когда сообщение посылается, неизвестно, достигнет ли оно


своего назначения — оно может потеряться по пути. Нет таких понятий, как
подтверждение, повторная передача, тайм-аут.
● Неупорядоченность — если два сообщения отправлены одному получателю,
то порядок их достижения цели не может быть предугадан.
● Легковесность — никакого упорядочивания сообщений, никакого отслеживания
соединений и т. д. Это небольшой транспортный уровень, разработанный на IP.
● Датаграммы — пакеты посылаются по отдельности и проверяются на
целостность только если они прибыли. Пакеты имеют определенные границы,
которые соблюдаются после получения, то есть операция чтения на
сокете-получателе выдаст сообщение таким, каким оно было изначально
послано.
● Нет контроля перегрузок — UDP сам по себе не избегает перегрузок. Для
приложений с большой пропускной способностью возможно вызвать коллапс
перегрузок, если только они не реализуют меры контроля на прикладном
уровне.
Highload

Прежде всего, highload — крайне относительное понятие. Оно никогда не измеряется


количеством запросов или скоростью работы сайта, т.к. попросту нет такого понятия,
как "средний сайт". Все сайты специфичны и одинаковое количество запросов может
приводить к совершенно разным нагрузкам на разные ресурсы.

Что же такое highload (читается "хайлоад")? Правильным вопросом будет скорее —


когда заканчивается "обычный" проект и начинается highload?

Когда наступает high load?


Наступает этот момент тогда, когда Ваша текущая инфраструктура начинает
показывать первые признаки того, что она перестает справляться с нагрузкой. Если у
Вас VPS на 128 Мб — для Вас это может быть 10 запросов в секунду. Для кого-то это
может быть 10 тысяч запросов. Суть не в них, а в том, существует ли необходимость
для масштабирования и оптимизации инфраструктуры.

Если Ваш сайт не справляется с нагрузкой — все, теперь Вы в клубе highload.

Как тюнить Mysql

innodb_buffer_pool_size
Если Вы используете только InnoDB таблицы, устанавливайте это значение
максимально возможным для Вашей системы. Буфер InnoDB кеширует и данные и
индексы. Поэтому значение этого ключа стоит устанавливать в 70%...80% всей
доступной памяти.

innodb_log_file_size
Эта опция влияет на скорость записи. Она устанавливает размер лога операций (так
операции сначала записываются в лог, а потом применяются к данным на диске). Чем
больше этот лог, тем быстрее будут работать записи (т.к. их поместится больше в файл
лога). Файлов всегда два, а их размер одинаковый. Значением параметра задается
размер одного файла:

Стоит понимать, что увеличение этого параметра увеличит и время восстановления


системы при сбоях. Это происходит потому, что при запуске системы все данные из
логов будет накатываться на данные. Однако с каждой новой версией,
производительность этого процесса растет.
innodb_log_buffer_size
Это размер буфера транзакций, которые не были еще закомичены. Значение этого
параметра стоит менять в случаях, если вы используете большие поля вроде BLOB
или TEXT.

innodb_file_per_table
Если включить эту опцию, Innodb будет сохранять данные всех таблиц в отдельных
файлах (вместо одного файла по умолчанию). Прироста в производительности не
будет, однако есть ряд преимуществ:

При удалении таблиц, диск будет освобождаться. По умолчанию общий файл данных
может только расширяться, но не уменьшаться.
Использование компрессионного формата таблиц потребует включить этот параметр.

innodb_flush_method
Этот параметр определяет логику сброса данных на диск. В современных системах
при использовании RAID и резервных узов, вы будете выбирать между O_DSYNC и
O_DIRECT:

innodb_flush_log_at_trx_commit
Изменение этого параметра может повысить пропускную способность записи данных в
базу в сотни раз. Он определяет, будет ли Mysql сбрасывать каждую операцию на диск
(в файл лога).

Тут следует руководствоваться такой логикой:

● innodb_flush_log_at_trx_commit = 1 для случаев, когда сохранность данных —


это приоритет номер один.
● innodb_flush_log_at_trx_commit = 2 для случаев, когда небольшая потеря
данных не критична (например, вы используете дублирование и сможете
восстановить небольшую потерю). В этом случае транзакции будут
сбрасываться в лог на диск только раз в секунду.
● Устанавливайте значение на свое усмотрение, однако в большинстве случаев
подойдет второй вариант:

query_cache_size
Значение этого параметра определяет сколько памяти стоит использовать под кеш
запросов. Самый правильный подход — не полагаться на этот механизм. На практике
он работает очень неэффективно. Так, весь кеш запросов для определенной таблицы
сбрасывается всякий раз, когда в таблицу вносится хотя бы одно изменение. Это
может привести к тому, что включение кеширования даже замедлит базу данных.

max_connections
Не следует изменять значение этого параметра на старте. Однако, если вы получаете
ошибки "Too many connections", эту опцию стоит поднимать. Она определяет
максимальное количество одновременных соединений с базой данных:
Событие composer

Composer запускает следующие именованные события во время его выполнения

Командные события
● pre-install-cmd: происходит до того, как команда install будет выполнена с
имеющимся файлом блокировки.
● post-install-cmd: возникает после того, как команда install была выполнена с
присутствующим файлом блокировки.
● pre-update-cmd: происходит до выполнения команды update или до
выполнения команды install без наличия файла блокировки.
● post-update-cmd: происходит после выполнения команды update или после
того, как команда install была выполнена без присутствия файла блокировки.
● post-status-cmd: возникает после выполнения команды status.
● pre-archive-cmd: происходит до выполнения команды archive.
● post-archive-cmd: происходит после выполнения команды archive.
● pre-autoload-dump: происходит до того, как автозагрузчик сбрасывается, либо
во время install/update, либо с помощью команды dump-autoload.
● post-autoload-dump: возникает после того, как автозагрузчик был сброшен,
либо во время install/update, либо с помощью команды dump-autoload.
● post-root-package-install: происходит после установки корневого пакета во
время команды create-project.
● post-create-project-cmd: происходит после выполнения команды create-project.

События установщика
● pre-dependencies-solving: происходит до разрешения зависимостей.
● post-dependencies-solving: происходит после устранения зависимостей.

События пакета
● pre-package-install: происходит до установки пакета.
● post-package-install: происходит после установки пакета.
● pre-package-update: происходит до обновления пакета.
● post-package-update: происходит после обновления пакета.
● pre-package-uninstall: происходит до удаления пакета.
● post-package-uninstall: происходит после удаления пакета.

События плагина
● init: происходит после инициализации экземпляра Composer.
● command: встречается перед выполнением любой команды Composer
Command на CLI. Он предоставляет вам доступ к входным и выходным
объектам программы.
● pre-file-download: происходит до загрузки файлов и позволяет вам
манипулировать объектом RemoteFilesystem до загрузки файлов на основе
загружаемого URL.
Корневой объект JSON в composer.json должен иметь свойство, называемое "scripts",
которое содержит пары именованных событий и соответствующие сценарии каждого
события. Скрипты события могут быть определены либо как строка (только для одного
сценария), либо как массив (для одного или нескольких сценариев).

Для каждого события:

● Скрипты выполняются в порядке, определенном при их соответствующем


событии.
● Массив скриптов, подключенных к одному событию, может содержать как
обратные вызовы PHP, так и исполняемые команды командной строки.
● Классы PHP, содержащие определенные обратные вызовы, должны быть
автозагружаемыми с помощью функции автозагрузки Composer.
● Обратные вызовы могут выполнять только автозагрузку классов из
определений psr-0, psr-4 и classmap. Если определенный обратный вызов
опирается на функции, определенные вне класса, сам обратный вызов отвечает
за загрузку файла, содержащего эти функции.

Dependency Injection vs Service locator vs Dependency


Injection Container
DI же в двух словах — вместо require/import модуля вы инжектируете зависимость
через параметр конструктора (или сеттер свойства). То есть за этим громким словом
стоит простое «передавайте зависимости класса через параметры конструктора. Всё.
DI — он именно об этом. Нужные нам зависимости предоставляются кем-то там. А где
этот "кто-то там" их берёт — DI это не волнует.

Локатор служб — широко известный анти-шаблон. А чем он занимается?


Предоставляет доступ одним объектам к другим объектам. Локатор представляет
собой контейнер, в который можно положить готовые объекты (или задать правила их
создания) и затем получить доступ к этим объектам. Локатору, по большому счёту, всё
равно, каким образом в нём оказываются объекты — созданы они извне явным
образом и помещены в контейнер или созданы самим контейнером согласно заданным
правилам. Локатор служб отвечает за хранение объектов и предоставление к ним
доступа. Всё.

Что такое DI-контейнер? Согласно вольного пересказа содержимого "Dependency


Injection Principles, Practices, and Patterns": "a software library that that provides DI
functionality and allows automating many of the tasks involved in Object Composition,
Interception, and Lifetime Management. DI Containers are also known as Inversion of
Control (IoC) Containers. (§3.2.2)"
Т.е., DI-контейнер в первую очередь отвечает за создание объектов, а лишь во
вторую — за их хранение. В DI-контейнере может вообще не хранится ни одного
созданного объекта, если само приложение не нуждается в объектах, общих для всего
приложения (типа конфигурации или логгера).
Чем же плох Service Locator?
А ничем. Плох не сам шаблон, а то, каким образом он иногда используется. В
частности, есть такое мнение, что "Service Locator нарушает инкапсуляцию в
статически типизированных языках, потому что этот паттерн нечётко выражает
предусловия". Плохо передавать Service Locator как зависимость.

Composition Root
Говоря о Внедрении Зависимостей мы не можем не прийти к такому понятию, как
Composition Root (далее я буду назвать это "Точка Сборки"). Это тот самый "кто-то",
кому делегированы обязанности по созданию зависимостей и их внедрению.
В Точке Сборки все зависимости явно определяются, соответствующие объекты
создаются и внедряются туда, где их ждут. Здесь различия между Локатором Служб и
DI-контейнером минимальны. И тот и другой позволяют создавать новые объекты,
хранить созданные объекты, извлекать хранимые объекты. Я бы даже взялся
утверждать, что в этом месте принципиальных различий между ними нет.

Главное отличие
Сервис локатор обычно передаётся как зависимость, и у него на каждый создаваемый
объект может быть отдельный метод создания. Это нарушает принцип разделения
интерфейсов, так как мы передаём его в класс радил одного-дву методов, а получаем
зависимость от интерфейса с 100500 методов.

Легальное применение Контейнера


Таким образом, является ли Контейнер DI-контейнером или контейнером Локатора
Служб, очень сильно зависит от того, где и каким образом мы его используем. Как я
уже сказал выше, в Точке Сборки разница между типами контейнеров исчезает. Но что
мы передаём, если контейнер сам является зависимостью для какого-либо класса?

UML нотация

Элементы диаграммы
Диаграмма классов является ключевым элементом в объектно-ориентированном
моделировании. На диаграмме классы представлены в рамках, содержащих три
компонента:
● В верхней части написано имя класса. Имя класса выравнивается по центру
и пишется полужирным шрифтом. Имена классов начинаются с заглавной
буквы. Если класс абстрактный — то его имя пишется полужирным курсивом.
● Посередине располагаются поля (атрибуты) класса. Они выровнены по
левому краю и начинаются с маленькой буквы.
● Нижняя часть содержит методы класса. Они также выровнены по левому
краю и пишутся с маленькой буквы.

Видимость
Для задания видимости членов класса (то есть — любым атрибутам или методам), эти
обозначения должны быть размещены перед именем участника.

● + Публичный (Public)
● - Приватный (Private)
● # Защищённый (Protected)
● / Производный (Derived) (может быть совмещён с другими)
● ~ Пакет (Package)

Области действия
UML определяет два типа областей действия для членов: экземпляр и классификатор,
последние имеют подчёркнутые имена.[5]

Члены классификаторы. Во многих языках называются static. Область действия —


сам класс.
Значения полей одинаковы для всех экземпляров в данной единице трансляции
Вызов метода не меняет состояние объекта

Члены экземпляры. Область действия — объект.


Значения полей могут отличаться в разных объектах
Методы могут изменять поля
Чтобы показать принадлежность к классификатору, имя подчёркивается, в противном
случае область действия полагается областью действия по-умолчанию.

Взаимосвязи
Взаимосвязи объектов классов

● Зависимость обозначает такое отношение между классами, что изменение


спецификации класса-поставщика может повлиять на работу зависимого
класса, но не наоборот.
● Ассоциация показывает, что объекты одной сущности (класса) связаны с
объектами другой сущности таким образом, что можно перемещаться от
объектов одного класса к другому. Является общим случаем композиции и
агрегации.
● Агрегация — это разновидность ассоциации при отношении между целым и его
частями. Как тип ассоциации агрегация может быть именованной. Одно
отношение агрегации не может включать более двух классов (контейнер и
содержимое). Если контейнер будет уничтожен, то его содержимое — нет.
● Композиция — более строгий вариант агрегации. Известна также как агрегация
по значению.Композиция имеет жёсткую зависимость времени существования
экземпляров класса контейнера и экземпляров содержащихся классов. Если
контейнер будет уничтожен, то всё его содержимое будет также уничтожено.

Взаимосвязи классов

● Обобщение (наследование) - Обобщение (Generalization) показывает, что один


из двух связанных классов (подтип) является частной формой другого
(надтипа), который называется обобщением первого. На практике это означает,
что любой экземпляр подтипа является также экземпляром надтипа.
● Реализация — отношение между двумя элементами модели, в котором один
элемент (клиент) реализует поведение, заданное другим (поставщиком).
Реализация — отношение целое-часть.

Общая взаимосвязь

● Зависимость (dependency) — это слабая форма отношения использования,


при которой изменение в спецификации одного влечёт за собой изменение
другого, причём обратное не обязательно. Возникает, когда объект выступает,
например, в форме параметра или локальной переменной.
● Уточнения отношений — Уточнение имеет отношение к уровню детализации.
Один пакет уточняет другой, если в нём содержатся те же самые элементы, но в
более подробном представлении.
● Мощность отношений (Кратность) Мощность отношения (мультипликатор)
означает число связей между каждым экземпляром класса (объектом) в начале
линии с экземпляром класса в её конце.

Типы мощности отношений

Виртуальные машины vs контейнеры


В отличие от виртуальных машин, контейнеры не создают такой дополнительной
нагрузки, поэтому с ними можно использовать систему и ресурсы более эффективно.

Стандарт в индустрии на сегодняшний день — это использовать виртуальные машины


для запуска приложений. Виртуальные машины запускают приложения внутри
гостевой операционной системы, которая работает на виртуальном железе основной
операционной системы сервера.

Виртуальные машины отлично подходят для полной изоляции процесса для


приложения: почти никакие проблемы основной операционной системы не могут
повлиять на софт гостевой ОС, и наоборот. Но за такую изоляцию приходится платить.
Существует значительная вычислительная нагрузка, необходимая для виртуализации
железа гостевой ОС.

Контейнеры используют другой подход: они предоставляют схожий с виртуальными


машинами уровень изоляции, но благодаря правильному задействованию
низкоуровневых механизмов основной операционной системы делают это с в разы
меньшей нагрузкой.
Docker
Простыми словами, Докер это инструмент, который позволяет разработчикам,
системными администраторам и другим специалистам деплоить их приложения в
песочнице (которые называются контейнерами), для запуска на целевой операционной
системе, например, Linux. Ключевое преимущество Докера в том, что он позволяет
пользователям упаковать приложение со всеми его зависимостями в
стандартизированный модуль для разработки

Команды

docker run - запускает контейнер


docker run %container% echo “foobar” - запускает контейнер и выполняет команду
docker run -it подключает интерактивный tty в контейнер. Теперь можно запускать
сколько угодно много команд внутри.
docker run -rm - тогда контейнер будет автоматически удаляться при завершении.
docker run -d - открепит (detach) терминал
docker run -P - сделает все открытые порты публичными и случайными
docker run --name - это имя, которое мы хотим дать контейнеру.
docker pull - скачивает образ busybox из регистра Докера и сохраняет его локально.
docker images - выводит список образов в системе
docker ps - выводит список запущенных контейнеров
docker ps -a - выводит список контейнеров, который мы когда-либо запускали
docker rm - удалить контейнеры
docker rm $(docker ps -a -q -f status=exited) - удалить все контейнеры со статусом
exited. -q возвращает только численные ID, -f фильтрует вывод на основе предоставленных
условий, -rm, тогда контейнер будет автоматически удаляться при завершении.
docker rmi - удаляет ненужные образы командой
docker port %container% - возвращает порты контейнера
docker stop %id% - останавливает контейнер
docker commit - изменяет образ
docker search - поиск по регистру
docker build - создает образ по dockerfile

Терминология

● Images (образы) - Схемы нашего приложения, которые являются основой


контейнеров. В примере выше мы использовали команду docker pull чтобы
скачать образ busybox.
● Containers (контейнеры) - Создаются на основе образа и запускают само
приложение. Мы создали контейнер командой docker run, и использовали образ
busybox, скачанный ранее. Список запущенных контейнеров можно увидеть с
помощью команды docker ps.
● Docker Daemon (демон Докера) - Фоновый сервис, запущенный на
хост-машине, который отвечает за создание, запуск и уничтожение
Докер-контейнеров. Демон — это процесс, который запущен на операционной
системе, с которой взаимодействует клиент.
● Docker Client (клиент Докера) - Утилита командной строки, которая позволяет
пользователю взаимодействовать с демоном. Существуют другие формы
клиента, например, Kitematic, с графическим интерфейсом.\
● Docker Hub - Регистр Докер-образов. Грубо говоря, архив всех доступных
образов. Если нужно, то можно содержать собственный регистр и использовать
его для получения образов.
● TAG конкретный снимок или снэпшот (snapshot) образа. latest - по умолчанию
● Base images (базовые образы) — это образы, которые не имеют
родительского образа. Обычно это образы с операционной системой, такие как
ubuntu, busybox или debian.
● Child images (дочерние образы) — это образы, построенные на базовых
образах и обладающие дополнительной функциональностью.
● Официальные образы — это образы, которые официально поддерживаются
командой Docker. Обычно в их названии одно слово. В списке выше python,
ubuntu, busybox и hello-world — базовые образы.
● Пользовательские образы — образы, созданные простыми пользователями
вроде меня и вас. Они построены на базовых образах. Обычно, они называются
по формату user/image-name.
● onbuild - Эти образы включают несколько триггеров ONBUILD, которых обычно
достаточно чтобы быстро развернуть приложение. При сборке будет скопирован
файл requirements.txt, будет запущен pip install с этим файлом, а потом текущая
директория будет скопирована в /usr/src/app.
● Dockerfile - текстовый файл, в котором содержится список команд
Докер-клиента. Это простой способ автоматизировать процесс создания
образа. Самое классное, что команды в Dockerfile почти идентичны своим
аналогам в Linux. Это значит, что в принципе не нужно изучать никакой новый
синтаксис чтобы начать работать с докерфайлами.

Порты
80 - http
443 - https

Dockerfile

Текстовый файл, в котором содержится список команд Докер-клиента. Это простой


способ автоматизировать процесс создания образа. Самое классное, что команды в
Dockerfile почти идентичны своим аналогам в Linux. Это значит, что в принципе не
нужно изучать никакой новый синтаксис чтобы начать работать с докерфайлами.

● FROM - базовый образ


● EXPOSE - указывает порт
● CMD - команда для запуска приложения
● WORKDIR - указывает рабочую директорию

Docker-compose

docker-compose up -d
docker-compose down -v --remove-orphans
docker-compose logs -f

docker-compose run --rm php-fpm vendor/bin/phpunit --testsuite unit

Перцентиль vs Процент
Перцентиль – это способ посмотреть на ваши данные в отношении ко всем другим
значениям набора данных. Например, если вы хотите определить 10% самых активных
покупателей за прошлый месяц, по сути, вы хотите увидеть всех покупателей выше
границы в 90%.

Процентили делят всю выборку на определенные части. Например, пятый процентиль


охватывает 5% объема выборки. Предположим, показатель Ивана равен пятому
процентилю. Это означает, что Иван написал тест лучше, чем 5% студентов (10
человек из 200 получили от нуля до 70 баллов). Не густо, поскольку в этом случае
остальные 190 человек набрали больше, чем 70. Значит, тест был очень легкий и порог
в 66 баллов можно и повысить.

Но в том же самом тесте может быть и обратная ситуация: результат Ивана равен
90-ому процентилю. Это значит, что Иван написал тест лучше, чем 90% студентов. Или
по другому: только 10% (20 человек) набрали более 70 правильных ответов.
Следовательно, тест был весьма трудным. Преимущество метода еще и в том, что
разбивкой на процентили можно сравнивать тесты с разным числом участников.

Процентиль можно пояснить и на примере симметричного распределения Гаусса,


которое часто встречается в статистике для оценки веса, роста и т.п. На рисунке выше
показаны 25, 50, 75 и 100 процентили. Случаи 25 и 75-ого процентиля, включающие
четверть и три четверти выборки соответственно, называются квартилями.
С какими проектами по объему когда вы обычно работали

cms количество строк - 321к строк


saas количество строк - 522к строк

С какими по объёму базами вы обычно работали


Обычно до 3-5 гигабайт, максимально до 30 гигабайт

load average
Load Average — это среднее значение загрузки системы за некоторый период времени
(1, 5 и 15 минут).

В общем виде Load Average это среднее количество ожидающих ресурсов ЦПУ
процессов за один из трех промежутков времени. Так же нам известно, что это
значение в нормальном состоянии находится в диапазоне от 0 до 1, и единица
соответствует 100% загрузке одноядерной системы без перегруза.

● 0.00 означает, что на мосту нет ни одной машины. Фактически, значения от


0.00 до 1.00 означают отсутствие очереди. Подъезжающая машина может
воспользоваться мостом без ожидания;
● 1.00 означает, что на мосту находится как раз столько автомобилей,
сколько он может вместить. Все еще идет хорошо, но, в случае увеличения
потока машин, возможны проблемы;
● Значения, превышающие 1.00 означают наличие очереди на въезде.
Насколько большой? Например, значение 2.00 показывает, что в очереди стоит
столько же автомобилей, сколько движется по мосту. 3.00 означает.

Это число скейлиться от количество процессоров, то есть 1.00 для четырехядерного


процессора это 4.00.

Команда cat /proc/cpuinfo выводит информацию обо всех процессорах в вашей


системе. Чтобы узнать количество ядер, «скормите» ее вывод утилите grep:

cat /proc/cpuinfo | grep 'cpu cores'


Когда не нужно использовать очереди

● Когда обработка сообщений не терпит отлагательств;


● Когда мы должны гарантировать, что сообщение должно будет обработано
ровно один раз (например операция неидемпотентая);
● Когда будет очень трудно восстановить данные после падения очереди;

Когда использовать UNION селекты

● UNION устраняет дубликаты, поэтому, если вы хотите, чтобы дубликаты были


включены, uyse UNION ALL
● При JOIN, результирующим набором будут отдельными столбцами в
результирующем наборе. Вам придется изучить каждый из столбцов,чтобы
выяснить, какая таблица соответствует.
● UNION работает, когда оба оператора SELECT имеют одинаковое количество
столбцов, AND столбцы имеют одинаковые (или, по крайней мере, похожие)
типы данных.
● UNION не имеет значения, если оба оператора SELECT выбирают данные
только из одной таблицы, или если один или оба из них уже являются JOIN s в
нескольких таблицах.
● UNION по умолчанию выполняет отдельную операцию для каждого оператора,
селективность каждого столбца не объединяется, давая ему больше шансов на
выполнение поиска. Теперь, поскольку UNION выполняет две операции, они
должны сопоставить свои результирующие наборы, используя вышеописанную
операцию конкатенации. Как правило, это не дорогостоящая операция.
● UNION ALL - это простая конкатенация, и ее следует использовать везде, где
это возможно, тогда как UNION будет неявно выполнять DISTINCT для
удаления дублирующихся кортежей.

Минусы внешних ключей

● нагрузка на вставки и поддержку целостности


● перенесение бизнес логики на базу данных
● сложности в изменении внешних ключей на больших данных

XSS когда экранировать данные


Когда получаем данные, так как хз, где они потом будет применены
Когда использовать интерфейсы
● Для пересечения границ
● Когда есть несколько реализацией одного абстрактного поведения

Можно ли менять режим доступа в дочернем класса


нет

Можно ли обратиться к приватном методу другого


экземпляра того же класса
можно, режим доступа определяется на уровне класса, а не экземпляра

SQL INJECTION когда экранировать данные


Перед сохранением в бд

SQL: Что вернет условие 2 <> NULL


false, так как null - в sql - значение неизвестно

SQL: Что вернет условие 3 NOT IN (1, 2, NULL)


false, так как null - в sql - значение неизвестно

SQL: Выполнится ли этот запрос?

𝑆𝐸𝐿𝐸𝐶𝑇 𝑜𝑟𝑑𝑒𝑟_𝑖𝑑, 𝑜𝑟𝑑𝑒𝑟_𝑐𝑜𝑑𝑒, 𝑆𝑈𝑀(𝑜𝑟𝑑𝑒𝑟_𝑣𝑎𝑙𝑢𝑒) 𝐹𝑅𝑂𝑀 𝑜𝑟𝑑𝑒𝑟𝑠 𝐺𝑅𝑂𝑈𝑃 𝐵𝑌𝑜𝑟𝑑𝑒𝑟_𝑖𝑑

Едино правильного ответа на этот вопрос нет — все зависит от базы данных.
Проблема этого запроса заключается в том, что колонка order_code не указана в
выражении GROUP BY и при этом для нее не определена агрегатная функция. То
есть по отношению к колонке order_code мы не знаем группировать ее или
группировать по ней.
Если этот запрос будет выполняться в MySQL, то колонка order_code добавится в
выражение GROUP BY автоматически и запрос выполнится нормально.

SQL: Почему не выполнится этот запрос?

𝑆𝐸𝐿𝐸𝐶𝑇 𝑢𝑠𝑒𝑟_𝑛𝑎𝑚𝑒, 𝑌𝐸𝐴𝑅(𝑢𝑠𝑒𝑟_𝑏𝑖𝑟𝑡ℎ_𝑑𝑎𝑡𝑒) 𝐴𝑆 𝑦𝑒𝑎𝑟_𝑜𝑓_𝑏𝑖𝑟𝑡ℎ𝐹𝑅𝑂𝑀 𝑢𝑠𝑒𝑟𝑠 𝑊𝐻𝐸𝑅𝐸 𝑦𝑒𝑎𝑟_𝑜𝑓_𝑏𝑖𝑟𝑡ℎ = 2000

Запрос не выполнится из-за обращения к псевдониму year_of_birth в выражении


WHERE. Дело в том, что псевдонимы полей в SQL используются для форматирования
данных уже полученных из базы. Поэтому их можно использовать только в
выражениях, которые отвечают за оформление результата, таких как GROUP BY,
ORDER BY и HAVING. В выражениях, отвечающих за получение данных, таких как
WHERE, нужно использовать оригинальные имена полей.

SQL: Имеет ли значение порядок колонок в составном


индексе?

При создании составного индекса сначала строится обычный индекс для его первой
колонки, а потом уже на основе него строится индекс для второй колонки и так дальше.

Другими словами, колонки, по которым поиск выполняется чаще всего, должны стоять
в составном индексе первыми.

SQL: Какая разница между TRUNCATE TABLE table_name и


DELETE FROM table_name

Фактически обе эти команды вызовут удаление всех строк из таблицы под названием
table_name, но вот произойдет это совсем по-разному:

● При вызове команды TRUNCATE таблица полностью сбрасывается и создается


снова, в то время как команда DELETE удаляет каждую строку таблицы по
отдельности. Из-за этого TRUNCATE отрабатывает значительно быстрее.
● Как следствие первого пункта, команда TRUNCATE не вызывает срабатывание
триггеров и правил внешних ключей, то есть, очищая таблицу таким способом,
можно не бояться каскадного удаления или изменения данных в других
таблицах.
● В отличие от DELETE команда TRUNCATE не транзакционная. То есть, если в
момент ее вызова, таблица table_name будет заблокирована какой-либо
транзакцией — может возникнуть ошибка.
● TRUNCATE — это команда DDL, а DELETE — команда DML.
● TRUNCATE не будет работать, если таблица содержит внешние ключи. В этом
случае придется использовать DELETE.

SQL: Какая разница между типами CHAR и VARCHAR

Оба эти типа используются для хранения текстовой информации ограниченной длины,
а различия между ними следующие:

● Тип CHAR хранит значение фиксированной длины. Если строка,


помещаемая в колонку данного типа, имеет меньшую длину, чем длина типа —
строка будет дополнена пробелами. Например, если в колонку типа CHAR(10)
записать строку SQL, то она сохранится как SQL .
● Тип VARCHAR хранит значение переменной длины. Под каждое значение
этого типа выделяется столько памяти, сколько нужно для этого конкретного
значения.
● Для типа CHAR используется статическое распределение памяти, из-за чего
операции с ним быстрее, чем с VARCHAR.
Таким образом, тип CHAR подходит для хранения строковых данных фиксированной
длины (например, инвентарных номеров, хешей), а для остальных строк больше
подойдут VARCHAR или NVARCHAR.

SQL: Какая разница между типами VARCHAR и NVARCHAR

● Тип NVARCHAR, пожалуй, самый универсальный из строчных типов данных в


БД. Он позволяет хранить строки переменной длины в формате Unicode. В
этом формате каждый символ занимает 2 байта, а сама кодировка содержит 65
536 символов и включает в себя все языки мира, в том числе иероглифы.
● Тип VARCHAR хранит данные в формате SACII. В этом формате каждый символ
занимает 1 байт, но отельная кодировка содержит всего 256 символов. Из-за
этого для каждого мирового языка выделяется своя кодировка.

Таким образом, в формате VARCHAR стоит хранить строчные данные, которые точно
не придется переводить (например, адреса электронной почты). Для других случаев
больше подойдет NVARCHAR.

SQL: Какая разница между UNION и UNION ALL

Выражения UNION и UNION ALL — это очень надежные поставщики лишних или
недостающих строк в результате запроса. Оба эти выражения используются, чтобы
объединить результаты нескольких независимых друг от друга запросов. А
разница между ними заключается в том, что, если в результатах запросов есть
одинаковые строки, то UNION удалит дубликаты, оставив только одну из таких строк.
В то же время UNION ALL, как можно догадаться из названия, просто объединит
результаты запросов, не обращая внимания на дубликаты.

SQL: Какая разница между выражениями WHERE и


HAVING

Ну и наконец, вопрос, который задают практически на каждом собеседовании по базам


данных: про HAVING.
Выражения WHERE и HAVING используются для фильтрации результата запроса и
ожидают после себя некоторое условие, по которому нужно отфильтровать данные.
Но, если WHERE работает само по себе и фильтрует данные каждой строки
результата по отдельности, то выражение HAVING имеет смысл только в сочетании с
выражением GROUP BY и фильтрует уже сгруппированные значения.

WHERE HAVING

Реализ Строковых операциях Столбцовых операциях


овано в
Относи Отдельной строке Суммированной строке или
тся к группам
Исполь Выборки конкретных данных Выборки всех данных и
зуется из определенных строк, отделения тех из них, которые
для согласно заданным условиям соответствуют заданным
условиям
Агрегат Не может содержать Может содержать
ные
функци
и
Операт Может использоваться с Не может использоваться без
оры SELECT, UPDATE и DELETE оператора SELECT
Выраже Идет после выражения WHERE Идет перед выражением HAVING
ние
GROUP
BY
SQL: Что такое SQL

SQL расшифровывается как «Structured Query Language» — «язык структурированных


запросов». SQL - декларативный.

SQL: Расскажите о разных видах команд SQL

Операторы определения данных (англ. Data Definition Language, DDL)


DDL — это часть SQL, которая служит для определения структуры данных в
начальном состоянии, когда база данных только создается. Операторы определения
данных используются, главным образом, для создания и реструктуризации объектов
базы данных.

● create
● alter
● drop
● truncate
Операторы манипуляции данными (англ. Data Manipulation Language, DML)
DML используется для работы с уже существующими данными, содержащимися в базе
данных. С помощью этих операторов пользователи могут получать данные из базы и
совершать над ними какие-то манипуляции.

● select
● insert
● update
● delete

Операторы определения доступа к данным (англ. Data Control Language, DCL)


CL используется для контроля доступа к данным в базе данных. Команды DCL обычно
служат для создания объектов, имеющих отношение к доступу пользователей к базе, а
также к распределению разрешений между пользователями.

● grant
● revoke

Операторы управления транзакциями (англ. Transaction Control Language, TCL)


TCL используется для контроля изменений, осуществленных при помощи DML. Также с
помощью TCL происходит объединение операторов в логические транзакции.

● commit
● rollback
● savepoint
● begin
● transaction
SQL: Что такое ограничение по умолчанию?

Ограничения используются для установки определенных правил обработки данных и


указания типов данных, которые могут попадать в таблицу. Это что касается
ограничений вообще. Теперь давайте рассмотрим ограничения по умолчанию.

Ограничение по умолчанию (DEFAULT) используется для определения дефолтного


значения для столбца, которое будет автоматически добавляться во все новые записи,
если нужное значение не будет задано явно.

SQL: Что такое ограничение уникальности?

Ограничения уникальности (UNIQUE) используются для обеспечения уникальности


всех значений в столбце (т. е., чтобы все значения непременно были разными).

SQL: Как бы вы нашли вторую по величине зарплату в этой


таблице?

𝑠𝑒𝑙𝑒𝑐𝑡 𝑚𝑎𝑥(𝑒_𝑠𝑎𝑙𝑎𝑟𝑦) 𝑓𝑟𝑜𝑚 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒 𝑤ℎ𝑒𝑟𝑒 𝑒_𝑠𝑎𝑙𝑎𝑟𝑦 𝑛𝑜𝑡 𝑖𝑛 (𝑠𝑒𝑙𝑒𝑐𝑡 𝑚𝑎𝑥(𝑒_𝑠𝑎𝑙𝑎𝑟𝑦) 𝑓𝑟𝑜𝑚 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒)

SQL: Что такое первичный ключ?

Первичный ключ используется в качестве уникального идентификатора для всех


записей в таблице. Он не моет иметь значение NULL, кроме того, его значение должно
быть уникальным. Первичный ключ может состоять из одного или нескольких полей.

SQL: Что такое внешний ключ?

Внешний ключ это атрибут или набор атрибутов, ссылающийся на первичный ключ в
какой-нибудь другой таблице. В общем, он используется для связи между двумя
таблицами.

SQL: Что такое индекс?

Индексы помогают ускорить поиск в базе данных. Если в выражении WHERE не задан
индекс никакого столбца, SQL-сервер в поиске соответствия будет проверять каждую
строку во всей таблице. Если у вас много данных, эта операция может оказаться
довольно медленной.

Индексы используются для поиска всех строк, совпадающих по каким-то столбцам, а


затем уже в этих выборках ведется поиск нужных данных.

SQL: Расскажите о видах индексов

● Простые индексы. Создаются только для одного столбца таблицы.


● Составные индексы. Создаются для двух или большего количества столбцов
таблицы.
● Уникальные индексы. Используются для поддержания целостности данных
таблицы. Они не дают вставлять в таблицу несколько значений.

SQL: Поясните разницу между кластерными и


некластерными индексами

● Кластерный индекс используется для сортировки данных в строках по их


ключевым значениям. Кластерный индекс напоминает телефонный
справочник. Мы можем открыть справочник на David (например, в поисках
«David, Thompson») и найти информацию обо всех Дэвидах, по порядку.
Поскольку данные расположены друг за другом, это помогает выбирать их в
запросах с указанием диапазона. Также кластерный индекс имеет отношение к
тому, как, собственно, хранятся данные. В таблице может быть только один
кластерный индекс.
● Некластерный индекс хранит данные в одном месте, а индексы — в
другом. Этот индекс имеет указатели на расположение данных. Поскольку
индекс не хранится там же, где и данные, для каждой таблицы может
существовать много некластерных индексов.

Параметры Кластерный индекс Некластерный индекс


Используетс Сортировки и хранения Создания логического порядка для
я для записей в памяти строк данных. Указатели
(физически) указывают на физические файлы с
данными
Методы Хранит данные в Никогда не хранит данные в
хранения лиственных узлах лиственных узлах индекса
индекса
Размер Довольно большой Сравнительно маленький
Доступ к Быстрый Медленный
данным
Дополнител Не требуется Требуется для отдельного хранения
ьное индексов
дисковое
пространств
о
Тип ключа По умолчанию Может использоваться с
первичный ключ ограничением уникальности в
таблицы является таблице, которая выступает в роли
кластерным индексом составного ключа
Отличитель Улучшает Должен создаваться в столбцах,
ная производительность используемых в JOIN
особенност при получении данных
ь

SQL: Расскажите, чем отличаются SQL и PL/SQL

SQL PL/SQL
SQL это структурированный язык Это язык программирования для
запросов к базам данных. баз данных, использующий SQL.
SQL это отдельный запрос, который PL/SQL это блок кодов,
используется для выполнения используемый для написания всей
команд DML и DDL. процедуры или функции.
SQL это декларативный язык, PL/SQL это процедурный язык,
ориентированный на данные. ориентированный на приложение.
Используется главным образом для Используется для создания
манипуляций с данными. приложения.
Предоставляет возможность Не предоставляет возможности
взаимодействия с сервером базы взаимодействия с сервером базы
данных. данных.
Не может содержать в себе код Может содержать SQL, поскольку
PL/SQL. сам является расширением SQL.
SQL: Как вы понимаете символьные функции?
Символьные функции используются для манипуляций с символами. К ним относятся:

● UPPER
● LOWER
● INITCAP
● CONCAT
● LENGTH
● SUBSTRING

SQL: Что такое AUTO_INCREMENT?


AUTO_INCREMENT используется в SQL для автоматической генерации уникального
номера при каждом добавлении записи в таблицу.

Поскольку первичный ключ уникален для каждой записи, мы добавляем это поле в
качестве AUTO_INCREMENT поля, таким образом при каждой вставке новой записи
номер будет увеличиваться автоматически.

SQL: Что такое СУБД?


Допустим, есть большая база данных, которой пользуются многие сотрудники: кто-то
ищет информацию, а кто-то изменяет или даже удаляет её. Чтобы правильно
обрабатывать все эти запросы, нужно специальное программное обеспечение, и
именно такое ПО получило название системы управления базами данных (СУБД).

SQL: Какие типы СУБД в соответствии с моделями данных


вы знаете?

● Реляционные
● Flat File — базы данных с двумерными файлами, в которых содержатся
записи одного типа и отсутствует связь с другими файлами, как в реляционных.
● Иерархические подразумевают наличие записей, связанных друг с другом по
принципу отношений один-к-одному или один-ко-многим.
● Сетевые похожи на иерархические, но в этом случае «ребёнок» может иметь
несколько «родителей» и наоборот.
● Объектно-ориентированные СУБД работают с базами данных, которые
состоят из объектов, используемых в ООП. Объекты группируются в классы и
называются экземплярами, а классы в свою очередь взаимодействуют через
методы.
● Объектно-реляционные обладают преимуществами реляционной и
объектно-ориентированной моделей.
● Многомерная модель является разновидностью реляционной и использует
многомерные структуры. Часто представляется в виде кубов данных.
● Гибридные состоят из двух и более типов баз данных. Используются в том
случае, если одного типа недостаточно для обработки всех запросов.

SQL: Какие ещё ограничения вы знаете, как они работают и


указываются?

● UNIQUE — гарантирует уникальность значений в столбце;


● NOT NULL — значение не может быть NULL;
● INDEX — создаёт индексы в таблице для быстрого поиска/запросов;
● CHECK — значения столбца должны соответствовать заданным условиям;
● DEFAULT — предоставляет столбцу значения по умолчанию.

SQL: Для чего используется ключевое слово ORDER BY

Для сортировки данных в порядке возрастания (ASC) или убывания (DESC) или
случайный (RAND).

SQL: Разница между inner, outer, right и left join

В SQL доступны разные типы соединений:

INNER JOIN: возвращает строки, когда есть совпадение в обеих таблицах (default)

LEFT JOIN: возвращает все строки из левой таблицы, даже если в правой таблице нет
совпадений.

RIGHT JOIN: возвращает все строки из правой таблицы, даже если в левой таблице
нет совпадений.

FULL OUTER JOIN: Он объединяет результаты как левого, так и правого внешних
соединений.

Объединенная таблица будет содержать все записи из обеих таблиц и заполнять NULL
для отсутствия совпадений с обеих сторон.

SELF JOIN: используется для объединения таблицы в себя, как если бы таблица была
двумя таблицами, временно переименовывая по крайней мере одну таблицу в
SQL-заявлении.
CARTESIAN JOIN: возвращает декартово произведение наборов записей из двух или
более объединенных таблиц.

Для INNER присоединяется порядок не имеет значения

Для (ВЛЕВО, ВПРАВОЕ ИЛИ ПОЛНОЕ) ВНЕШНИЕ соединения, порядок

SQL: Как работают подстановочные знаки?

Это специальные символы, которые нужны для замены каких-либо знаков в запросе.
Они используются вместе с оператором LIKE, с помощью которого можно
отфильтровать запрашиваемые данные.

● % — заменить ноль или более символов;


● _ — заменить один символ.

SQL: Что делают псевдонимы Aliases?

SQL-псевдонимы нужны для того, чтобы дать временное имя таблице или столбцу. Это
нужно, когда в запросе есть таблицы или столбцы с неоднозначными именами. В этом
случае для удобства в составлении запроса используются псевдонимы.
SQL-псевдоним существует только на время запроса.

SQL: Для чего нужен оператор INSERT INTO SELECT?


Данный оператор копирует данные из одной таблицы и вставляет их в другую, при
этом типы данных в обеих таблицах должны соответствовать.

SQL: Что такое нормализация и денормализация?


Нормализация отношений в SQL призвана организовать информацию в базе данных
таким образом, чтобы она не занимала много места и с ней было удобно работать. Это
удаление избыточных данных, устранение дублей, идентификация наборов связанных
данных через PRIMARY KEY, etc.

Соответственно, денормализация является обратным процессом, который вносит в


нормализованную таблицу избыточные данные.
SQL: Как выбрать записи с нечётными Id?

𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑠𝑎𝑚𝑝𝑙𝑒 𝑊𝐻𝐸𝑅𝐸 𝑖𝑑 % 2 ! = 0;

Если остаток от деления id на 2 равен нулю, перед нами чётное значение, и наоборот.

SQL: Как найти дубли в поле email?

𝑆𝐸𝐿𝐸𝐶𝑇 𝑒𝑚𝑎𝑖𝑙, 𝐶𝑂𝑈𝑁𝑇(𝑒𝑚𝑎𝑖𝑙) 𝐹𝑅𝑂𝑀 𝑐𝑢𝑠𝑡𝑜𝑚𝑒𝑟𝑠 𝐺𝑅𝑂𝑈𝑃 𝐵𝑌 𝑒𝑚𝑎𝑖𝑙 𝐻𝐴𝑉𝐼𝑁𝐺 𝐶𝑂𝑈𝑁𝑇(𝑒𝑚𝑎𝑖𝑙) > 1;

SQL: При выборке из таблицы прибавьте к дате 1 день

𝑆𝐸𝐿𝐸𝐶𝑇 𝐷𝐴𝑇𝐸_𝐴𝐷𝐷(𝑑𝑎𝑡𝑒, 1 𝐷𝐴𝑌) 𝑎𝑠 𝑛𝑒𝑤_𝑑𝑎𝑡𝑒 𝐹𝑅𝑂𝑀 𝑡𝑎𝑏𝑙𝑒;

SQL: Выберите только уникальные имена

𝑆𝐸𝐿𝐸𝐶𝑇 𝐷𝐼𝑆𝑇𝐼𝑁𝐶𝑇 𝑛𝑎𝑚𝑒 𝐹𝑅𝑂𝑀 𝑢𝑠𝑒𝑟𝑠;

SQL: Найдите в таблице среднюю зарплату работников

𝑆𝐸𝐿𝐸𝐶𝑇 𝐴𝑉𝐺(𝑠𝑎𝑙𝑎𝑟𝑦) 𝐹𝑅𝑂𝑀 𝑤𝑜𝑟𝑘𝑒𝑟𝑠;

SQL: А теперь получите список сотрудников с зарплатой


выше средней

𝑆𝐸𝐿𝐸𝐶𝑇 * 𝐹𝑅𝑂𝑀 𝑤𝑜𝑟𝑘𝑒𝑟𝑠𝑊𝐻𝐸𝑅𝐸 𝑠𝑎𝑙𝑎𝑟𝑦 > (𝑆𝐸𝐿𝐸𝐶𝑇 𝐴𝑉𝐺 (𝑠𝑎𝑙𝑎𝑟𝑦) 𝐹𝑅𝑂𝑀 𝑤𝑜𝑟𝑘𝑒𝑟𝑠);
SQL: Даны таблицы workers и departments. Найдите все
департаменты без единого сотрудника

𝑆𝐸𝐿𝐸𝐶𝑇 𝑑𝑒𝑝𝑎𝑟𝑡𝑚𝑒𝑛𝑡_𝑛𝑎𝑚𝑒
𝐹𝑅𝑂𝑀 𝑤𝑜𝑟𝑘𝑒𝑟𝑠 𝑤
𝑅𝐼𝐺𝐻𝑇 𝐽𝑂𝐼𝑁 𝑑𝑒𝑝𝑎𝑟𝑡𝑚𝑒𝑛𝑡𝑠 𝑑 𝑂𝑁 (𝑤. 𝑑𝑒𝑝𝑎𝑟𝑡𝑚𝑒𝑛𝑡_𝑖𝑑 = 𝑑. 𝑑𝑒𝑝𝑎𝑟𝑡𝑚𝑒𝑛𝑡_𝑖𝑑)
𝑊𝐻𝐸𝑅𝐸 𝑓𝑖𝑟𝑠𝑡_𝑛𝑎𝑚𝑒 𝐼𝑆 𝑁𝑈𝐿𝐿;

SQL: Замените в таблице зарплату работника на 1000, если


она равна 900, и на 1500 в остальных случаях

𝑈𝑃𝐷𝐴𝑇𝐸 𝑡𝑎𝑏𝑙𝑒 𝑆𝐸𝑇 𝑠𝑎𝑙𝑎𝑟𝑦 =


𝐶𝐴𝑆𝐸
𝑊𝐻𝐸𝑁 𝑠𝑎𝑙𝑎𝑟𝑦 = 900 𝑇𝐻𝐸𝑁 1000
𝐸𝐿𝑆𝐸 1500
𝐸𝑁𝐷;

SQL: При выборке из таблицы пользователей создайте


поле, которое будет включать в себя и имена, и зарплату

𝑆𝐸𝐿𝐸𝐶𝑇 𝐶𝑂𝑁𝐶𝐴𝑇(𝑛𝑎𝑚𝑒, 𝑠𝑎𝑙𝑎𝑟𝑦) 𝐴𝑆 𝑛𝑒𝑤_𝑓𝑖𝑒𝑙𝑑 𝐹𝑅𝑂𝑀 𝑢𝑠𝑒𝑟𝑠;

SQL: Переименуйте таблицу


𝐴𝐿𝑇𝐸𝑅 𝑇𝐴𝐵𝐿𝐸 𝑓𝑖𝑟𝑠𝑡_𝑡𝑎𝑏𝑙𝑒 𝑅𝐸𝑁𝐴𝑀𝐸 𝑠𝑒𝑐𝑜𝑛𝑑_𝑡𝑎𝑏𝑙𝑒;

SQL: Чем отличается IN от EXISTS?

Это еще один из популярных вопросов по SQL.

IN:

● Работает результирующим набором.


● Не применяется во вложенных запросах.
● Сравнивает все значения в списке результатов
● Имеет сравнительно низкую производительность при работе с
большими результатами и подзапросами.

EXISTS:

● Работает с виртуальными таблицами.


● Используется со связанными запросами.
● Выводит результаты сравнения, если true.
● Обладает высокой производительностью, что облегчает обработку
больших подзапросов.

SQL: Как Вы Отобразите Текущее Время и Дату с Помощью


SQL Запроса?

now()

SQL: Что Делать, Если Вы Забыли Ваш Пароль Для Root?

Если вы забыли или потеряли ваш пароль для рута, то запустите базу данных с
командой “skip-grants-table”. После того, как вы установите новый пароль,
перезагрузите базу данных в обычном режиме и введите новый пароль.

SQL: Что Необходимо Сделать, Если Диск Данных


Переполнен?
Вы можете столкнуться с ситуацией, когда вы полностью заполните ваш диск данных.
В таком случае работать с базой будет невозможно.

Подобные SQL задачи требуют от вас применения различных команд и функций. В


данном случае необходимо использовать нечто под названием символическая ссылка
(soft link). Эти ссылки создают место, где вы можете хранить ваши файлы .frm и .idb –
именно это вам и нужно будет сделать. Это решит проблему с перегрузкой и позволит
вам пройти SQL собеседование
SQL: Назовите Компоненты, Составляющие Самую
Базовую Архитектуру MySQL.

Самый базовый MySQL может состоять из трёх компонентов:


● Оптимизатора запросов;
● менеджера подключения;
● менеджер подключаемых движков.

SQL: Создайте Пустую Таблицу Из Существующей.

𝑆𝑒𝑙𝑒𝑐𝑡 * 𝑖𝑛𝑡𝑜 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒𝑐𝑜𝑝𝑦 𝑓𝑟𝑜𝑚 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒 𝑤ℎ𝑒𝑟𝑒 1 = 2

SQL: Как Получить Текущую Версию SQL?

𝑆𝐸𝐿𝐸𝐶𝑇 𝑉𝐸𝑅𝑆𝐼𝑂𝑁()

SQL: Как Бы Вы Получили Альтернативные Нечётные


Записи Из Таблицы?

𝑆𝑒𝑙𝑒𝑐𝑡 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒𝐼𝑑 𝑓𝑟𝑜𝑚 (𝑆𝑒𝑙𝑒𝑐𝑡 𝑟𝑜𝑤𝑛𝑜, 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒𝑡𝐼𝑑 𝑓𝑟𝑜𝑚 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒) 𝑤ℎ𝑒𝑟𝑒 𝑚𝑜𝑑(𝑟𝑜𝑤𝑛𝑜, 2) = 1

SQL: Дайте Объяснение Переменным в SQL.


Вам нужно знать только то, что в SQL существует два различных типа переменных –
локальные и глобальные.

Локальные переменные — это те, которые существуют только в одной, единственной


функции. В отличие от них, глобальные переменные могут находиться по всей
программе.

sql: Извлеките Общие Записи Из Двух Таблиц.

𝑆𝑒𝑙𝑒𝑐𝑡 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒𝐼𝐷 𝑓𝑟𝑜𝑚 𝑒𝑚𝑝𝑙𝑜𝑦𝑒𝑒. 𝐼𝑁𝑇𝐸𝑅𝑆𝐸𝐶𝑇 𝑆𝑒𝑙𝑒𝑐𝑡 𝐸𝑚𝑝𝑙𝑜𝑦𝑒𝑒𝐼𝐷 𝑓𝑟𝑜𝑚 𝑊𝑜𝑟𝑘𝑆ℎ𝑖𝑓𝑡


Кластерные ключи в InnoDB

Здесь всё просто. Каждая таблица InnoDB имеет кластерный ключ. Каждая. Без
исключения.

Гораздо интереснее, какие поля для этого выбираются.


● Если в таблице задан PRIMARY KEY — это он

● Иначе, если в таблице есть UNIQUE (уникальные) индексы — это


первый из них

● Иначе InnoDB самостоятельно создаёт скрытое поле с суррогатным


ID размером в 6 байт

Составные индексы в бд

Порядок индексов важен, нужно сначала использовать индексы, которые обладают


большей селективностью, то есть более уникальны (по значению можно
отфильтровать больше данных).

Префикс столбца часто оказывается весьма избирательным, чтобы обеспечить


хорошую производительность. Если вы индексируете столбцы типа BLOB или TEXT,
либо очень длинные столбцы типа VARCHAR, то обязаны определять префиксные
индексы, поскольку MySQL не позволяет индексировать такие столбцы по их полной
длине.

Сложность заключается в выборе длины префикса, которая должна быть достаточно


велика, чтобы обеспечить хорошую селективность, но не слишком велика, чтобы
сэкономить пространство. Префикс избирается настолько длинным, чтобы польза от
его использования была почти такая же, как от использования индекса по полному
столбцу. Другими словами, кардинальность префикса должна быть почти такой же, как
кардинальность всего столбца.
Зачем нужны колоночные БД

Основная идея колоночных СУБД — это хранение данных не по строкам, как это
делают традиционные СУБД, а по колонкам. Это означает, что с точки зрения
SQL-клиента данные представлены как обычно в виде таблиц, но физически эти
таблицы являются совокупностью колонок, каждая из которых по сути представляет
собой таблицу из одного поля. При этом физически на диске значения одного поля
хранятся последовательно друг за другом — приблизительно так:

[A1, A2, A3], [B1, B2, B3], [C1, C2, C3] и т.д.

Такая организация данных приводит к тому, что при выполнении select в


котором фигурируют только 3 поля из 50 полей таблицы, с диска физически
будут прочитаны только 3 колонки. Это означает что нагрузка на канал
ввода-вывода будет приблизительно в 50/3=17 раз меньше чем при выполнении такого
же запроса в традиционной СУБД.

Кроме того, при поколоночном хранении данных появляется замечательная


возможность сильно компрессировать данные, так как в одной колонке таблицы
данные как правило однотипные, чего не скажешь о строке

Колоночные СУБД призваны решить проблему неэффективной работы традиционных


СУБД в аналитических системах и системах в подавляющим большинством операций
типа «чтение». Они позволяют на более дешевом и маломощном оборудовании
получить прирост скорости выполнения запросов в 5, 10 и иногда даже в 100 раз, при
этом, благодаря компрессии, данные будут занимать на диске в 5-10 раз меньше, чем
в случае с традиционными СУБД.

У колоночных СУБД есть и недостатки — они медленно работают на запись, не


подходят для транзакционных систем и как правило, ввиду «молодости» имеют ряд
ограничений для разработчика, привыкшего к развитым традиционным СУБД.

CAS: Неблокирующая синхронизация


Обновить переменную этим новым значение, но отказать, если другой поток изменил
значение после моего последнего просмотра
Передача по ссылке массивов
используется для оптимизации, когда идет много работы над добавлением чего-либо в
массив

PHP-FPM
FPM (FastCGI Process Manager, менеджер процессов FastCGI) является
альтернативной реализацией PHP FastCGI с несколькими дополнительными
возможностями обычно используемыми для высоконагруженных сайтов.

Эти возможности включают в себя:

продвинутое управление процессами с корректной (graceful) процедурой остановки и


запуска;

возможность запуска воркеров с разными uid/gid/chroot/окружением, а также запуска на


различных портах с использованием разных php.ini (замещение safe_mode);

логирование стандартных потоков вывода (stdout) и ошибок (stderr);

аварийный перезапуск в случае внезапного разрушения opcode-кеша;

поддержка ускоренной загрузки (accelerated upload);

"slowlog" - логирование необычно медленно выполняющихся скриптов (не только их


имена, но также и их трассировки. Это достигается с помощью ptrace и других
подобных утилит для чтения данных исполнения удалённых процессов);

fastcgi_finish_request() - специальная функция для завершения запроса и сброса всех


буферов данных, причём процесс может продолжать выполнение каких-либо
длительных действий (конвертирование видео, обработка статистики и т.п.);

Динамическое/статическое порождение дочерних процессов;

Базовая информация о статусе SAPI (аналогично Apache mod_status);

Конфигурационный файл, основанный на php.ini.

CGI
CGI (от англ. Common Gateway Interface — «общий интерфейс шлюза») —
стандарт интерфейса, используемого для связи внешней программы с
веб-сервером. Программу, которая работает по такому интерфейсу совместно с
веб-сервером, принято называть шлюзом, хотя многие предпочитают названия
«скрипт» (сценарий) или «CGI-программа». По сути позволяет использовать консоль
ввода и вывода для взаимодействия с клиентом.

Сам интерфейс разработан таким образом, чтобы можно было использовать любой
язык программирования, который может работать со стандартными устройствами
ввода-вывода. Такими возможностями обладают даже скрипты для встроенных
командных интерпретаторов операционных систем, поэтому в простых случаях могут
использоваться даже командные скрипты.

Все скрипты, как правило, помещают в каталог cgi (или cgi-bin) сервера, но это не
обязательно: скрипт может располагаться где угодно, но при этом большинство
веб-серверов требует специальной настройки.

FastCGI
Интерфейс FastCGI — клиент-серверный протокол взаимодействия веб-сервера и
приложения, дальнейшее развитие технологии CGI. По сравнению с CGI является
более производительным и безопасным.

FastCGI снимает множество ограничений CGI-программ. Недостаток


CGI-программ в том, что они должны быть перезапущены веб-сервером при
каждом запросе, что приводит к понижению производительности. FastCGI,
вместо того чтобы создавать новые процессы для каждого нового запроса,
использует постоянно запущенные процессы для обработки множества
запросов. Это позволяет экономить время.

В то время как CGI-программы взаимодействуют с сервером через STDIN и STDOUT


запущенного CGI-процесса, FastCGI-процессы используют Unix Domain Sockets или
TCP/IP для связи с сервером. Это даёт следующее преимущество над обычными
CGI-программами: FastCGI-программы могут быть запущены не только на этом же
сервере, но и где угодно в сети. Также возможна обработка запросов несколькими
FastCGI-процессами, работающими параллельно.

Что такое fixture?

При написании тестов не редка ситуация, когда надо иметь фиксированное


воспроизводимое много раз состояние программы. Например, такая-то кнопочка
нажата, такой-то класс содержит такие-то значения.

Чтобы не приходилось каждый раз вручную создавать подобное состояние программы


используются fixture (фикстуры). Фикстуры позволяют сохранить состояние системы в
файл, а потом его от туда загрузить.
По-мимо тестов, фикстуры применяются для создания начального состояния системы.
Например, есть проект, который использует базу данных(БД). И возникает задача
развернуть проект на новом компьютере. Можно перетаскивать БД и чистить от
лишнего. А можно сохранить первичное состояние в файле и затем его подгрузить.

Чем отличается Mock от Stub? (PHPUnit)


Dummy

Dummy is passed around, but never actually called, or if it's called it responds with a default
answer (mostly null). It mainly exists to satisfy a list of arguments.

Stub

Stubs are used with query like methods - methods that return things, but it's not important if
they're actually called.

Mock

Mocks are used with command like methods - it's important that they're called, and we don't
care much about their return value (command methods don't usually return any value).

Diff
stubs verify state and the mocks verify behavior.

Иногда эти термины stubs и mock путают: разница в том, что стаб ничего не
проверяет, а лишь имитирует заданное состояние. А мок — это объект, у которого
есть ожидания. Например, что данный метод класса должен быть вызван
определенное число раз. Иными словами, ваш тест никогда не сломается из-за
«стаба», а вот из-за мока может.

С технической точки зрения это значит, что, используя стабы, мы проверяем


состояние тестируемого класса или результат выполненного метода. При
использовании мока мы проверяем, соответствуют ли ожидания мока
поведению тестируемого класса. Также лучше использовать не более одного
мока на тест. Иначе с высокой вероятностью вы нарушите принцип «тестировать
только одну вещь». При этом, в одном тесте может быть сколько угодно стабов или
же мок и стабы.

Почему возникают дедлоки

В оффициальной документации Mysql про типы блокировок написано совсем немного,


а именно:
Есть 2 типа блокировок — Shared (S) и Exclusive (X). Первый тип позволяет
только читать данные прикрытые этой блокировкой, второй — читать, писать,
удалять и (о чем скромно умолчали) — получить блокировку уровня S

Так же сказано что если Транзакция№1 владеет блокировкой типа S на строке r, то


другая Транзакция№2 может захватить эту блокировку. Чтобы получить блокировку
типа X на этой строке, второй транзакции придется тихо подождать в сторонке.

Если же Транзакция№1 владеет блокировкой типа X на строке r, то Транзакция№2 не


может ни захватить эту же блокировку, ни получить новую уровня S. Она опять тихо
идет и ждет пока Транзакция№1 освободит требуемую строку.

Здесь есть один важный момент, который необходимо усвоить: блокировки S и X — это
2 разные блокировки. Это не значит что блокировка S, это какое-то подмножество
блокировки X. Это две разных сущности.

Вернемся к дедлокам. На некоторых форумах я встречал вопросы «Как получит


deadlock в Mysql». На самом деле очень просто.

Все необходимы ингредиенты у нас имеются в наличии: две транзакции, блокировки


типа S и X и строка, на которую получают блокировки.

Краткий рецепт приготовления deadlock на одной строке


1) Транзакция№1 получает блокировку S и продолжает работу
2) Транзакция№2 пытается получить блокировку типа X и… начинает ждать когда
Транзакция№1 освободит блокировку S
3) Транзакция№1 пытается получить блокировку типа X и… начинает ждать когда
Транзакция№2 получит блокировку типа X и освободит её

BEGIN;
SELECT * FROM `testlock` WHERE id=1 LOCK IN SHARE MODE; /* GET S LOCK */
SELECT SLEEP(5);
SELECT * FROM `testlock` WHERE id=1 FOR UPDATE; /* TRY TO GET X LOCK */
COMMIT;

BEGIN;
SELECT * FROM `testlock` WHERE id=1 FOR UPDATE; /* TRY TO GET X LOCK -
DEADLOCK AND ROLLBACK HERE */
COMMIT;

Как же с этим бороться? Офф. сайт Mysql советует комититься почаще, а так же
перепроверять код ошибки и перепроводить откатившуюся транзакцию. Мне
кажется есть вариант получше — сразу получать блокировку типа X. Тогда на
третьем шаге нашего рецепта Транзакция№1 смогла бы получить свою законную
блокировку и спокойно завершиться
Напоследок скажу что определить причину deadlock поможет команда SHOW ENGINE
INNODB STATUS, которая показывает какие блокировки кто держит и какие ожидает

Что лучше: 4 маленьких индекса (по отдельному полю


каждому) или один комплексный, составной на все 4 поля?

Составной индекс по полям (A, B) всегда может использоваться вместо индекса (A), но
не может использоваться вместо индекса (B). Ну, если это стандартный B-Tree индекс.

Тем не менее, поиск по простому индексу (A) будет чуть быстрее, чем по составному
(A, B), из-за бо́льшего числа записей в одном ключевом узле дерева. Но на интах вы
этого не заметите.

В последних версиях MySQL наконец-то заработал merge index, поэтому можно


ставить отдельный индекс на каждое поле не заморачиваясь на составные
индексы. Советую вам для начала поступить именно так и прогнать все запросы
через EXPLAIN, если не увидите в последнем столбце merge index, то тогда уже
начинайте добавлять составные индексы.

MySQL имеет алгоритм использования нескольких индексов (index merge),


но работает этот алгоритм не очень часто, и только без order by.
Единственный разумный способ пытаться использовать index merge —
случаи выборки по разным столбцам с OR.

Во-первых, смотрим на клоз order by. Используемый индекс должен начинаться


с тех же столбцов что упомянуты в order by, в той же или в полностью обратной
сортировке. Если сортировка не прямая и не обратная — индекс не может быть
использован. Здесь есть одно но… MySQL до сих пор не поддерживает индексов
со смешанными сортировками. Индекс всегда asc. Так что если у вас есть order
by A asc, B desc — распрощайтесь с using index.

При каких условиях составные индексы не будут работать?


К примеру, есть индексы по полям — A, B, C, D, а в запросе мы проверяем только
B, C, D или вообще C или A и B.

сработает A, AB, ABC, ABCD

Когда работают индексы по непосредственному


сравнению, по битвинам, лайкам?
MySQL применяет индексы также для сравнений LIKE, если аргумент в выражении
LIKE представляет собой постоянную строку, не начинающуюся с символа-шаблона.
Например, следующие команды SELECT используют индексы:

MySQL обычно использует тот индекс, который находит наименьшее количество строк.
Индекс применяется для столбцов, которые сравниваются с помощью следующих
операторов: =, >, >=, <, <=, BETWEEN и LIKE с префиксом, не содержащим
шаблонного символа, такого как something%.

Если индекс не охватывает все уровни AND в выражении WHERE, то он не


применяется для оптимизации данного запроса. Другими словами: чтобы индекс
можно было использовать, префикс этого индекса должен входить в каждую группу
AND.

Если использование индекса требует от MySQL прохода более чем по 30% строк в
данной таблице (в таких случаях просмотр таблицы, по всей видимости, окажется
намного быстрее, так как потребуется выполнить меньше операций поиска). Следует
учитывать, что если подобный запрос использует LIMIT по отношению только к
извлекаемой части строк, то MySQL будет применять индекс в любом случае, так как
небольшое количество строк можно найти намного быстрее, чтобы вернуть результат.
Если диапазон изменения индекса может содержать величины NULL при
использовании выражений ORDER BY ... DESC.

В чём отличие UNIX-сокетов от TCP-сокетов

Сокет UNIX представляет собой механизм межпроцессного взаимодействия , который


позволяет осуществлять обмен данными между двунаправленных процессов ,
работающих на одной и той же машине.

Сокеты IP (особенно сокеты TCP / IP) - это механизм, позволяющий осуществлять


связь между процессами по сети.

Доменные сокеты UNIX знают, что они выполняются в одной и той же системе, поэтому
они могут избежать некоторых проверок и операций (например, маршрутизации); что
делает их быстрее и легче, чем IP-сокеты. Поэтому, если вы планируете
взаимодействовать с процессами на одном хосте, это лучший вариант, чем IP-сокеты.

сокеты домена UNIX подчиняются разрешениям файловой системы, в то время как


сокеты TCP можно контролировать только на уровне фильтра пакетов.

Вы можете перечислить локальные unix-сокеты своего компьютера с помощью


следующей команды:
netstat -a -p --unix
Разъем TCP / IP используется для связи по сетям TCP / IP. Подключенный
TCP-сокет идентифицируется по комбинации локального IP-адреса, локального
порта, удаленного IP-адреса и удаленного порта. Прослушивающий сокет TCP
определяется локальным портом и, возможно, локальным IP. AIUI по крайней
мере в сокетах Linux / TCP / IP всегда приводит к генерации и декодированию
пакетов TCP / IP, даже если клиент и сервер находятся на одном компьютере.

Сокет домена unix (иногда сокращенный до сокета unix), с другой стороны,


работает на одном компьютере. Прослушивающие сокеты живут в иерархии
файловой системы, и доступ к ним может контролироваться разрешениями
файловой системы.

Кроме того, процесс, принимающий соединение через сокет Unix, может


определить идентификатор пользователя процесса, который подключается. Это
может избежать необходимости в шаге аутентификации. Вместо того, чтобы
генерировать пароль для вашего сервера базы данных и включать его копию в код
вашего веб-приложения, вы можете просто сообщить серверу базы данных, что
пользователь, выполняющий веб-приложение, имеет доступ к соответствующей
учетной записи пользователя в базе данных.

Доменные сокеты UNIX знают, что они выполняются в одной и той же системе, поэтому
они могут избежать некоторых проверок и операций (например, маршрутизации);
что делает их более быстрыми и легкими, чем сокеты IP.

Когда рефакторить

Правило трёх:

● Делая что-то в первый раз, вы просто это делаете.


● Делая что-то аналогичное во второй раз, вы морщитесь от необходимости
повторения, но все-таки повторяете то же самое.
● Делая что-то похожее в третий раз, вы начинаете рефакторинг.

Когда делаете новую фичу:

● Рефакторинг помогает понять чужой код. Если код, в который нужно добавить
новую фичу, недостаточно ясный, рефакторинг позволяет сделать его
очевидней для вас и для того, кто будет работать с ним в будущем.
● Рефакторинг облегчает написание нового кода. После рефакторинга
добавление новой фичи происходит значительно более гладко и занимает
меньше времени.

Когда исправляете баги:


● Ошибки — как тараканы, любят жить в темных затхлых местах вашего кода.
Попробуйте навести порядок в коде и ошибки найдутся сами собой.
● Кроме того, вам не придется создавать специальные задачи для рефакторинга,
которые так не любят видеть в отчетах менеджеры.

Во время код-ревью

● Когда вы делаете ревью новой фичи, возможно это последний шанс почистить
код перед тем, как он окажется доступным публично.
● Лучше всего проводить такое ревью вместе с автором кода. В этом случае, вы
будете предлагать автору изменения, а потом вместе решать, насколько сложно
произвести то или иное изменение. При этом, небольшие изменения можно
будет осуществлять очень быстро.

Как рефакторить

Рефакторинг следует проводить серией небольших изменений, каждое из которых


делает существующий код чуть лучше, оставляя программу в рабочем состоянии.

Чек-лист правильно проведённого рефакторинга:

● Код должен стать чище.


● В процессе рефакторинга не создаётся новая функциональность.
● Все существующие тесты должны успешно проходить

Почему тесты могут не пройти:

● Вы допустили ошибку при изменении кода


● Ваши тесты были слишком низкоуровневыми. Чаще всего это случается из-за
того, что ваши тесты проверяют работу приватных методов классов.

чем отличается count(*) от count(column_name)


COUNT(*) -возвращает общее количество записей в таблице (включая NULL значащих
записей). COUNT(Column Name) -возвращает общее количество записей, не
относящихся к NULL. Это означает, что он игнорирует подсчет NULL-значных записей в
этом конкретном столбце.

Что быстрее array_map или foreach


Быстрее foreach, так как есть ovehead на работу с callback
Sphinx vs ElasticSearch

Sphinx — система полнотекстового поиска, обладающая очень высокой скоростью


индексации и поиска, отлично интегрированная с MySQL и PostgreSQL, имеющая API
для распространённых языков веб-программирования (PHP, Python, Java, Perl, Ruby и
C++). Sphinx написан на C++ и свободно распространяется по лицензии GNU GPL.
Сфинкс используется на Хабрахабре, в проекте Викимапия, в Craigslist, в vBulletin,
поддерживается системой управления сайтами 1С-Битрикс.

Elasticsearch — поисковая система, построенная на базе индекса Lucene.


Обеспечивает распределенную работу с данными, предоставляет RESTful интерфейс
и хранение JSON-документов без заранее определяемой структуры (т.н. schemaless).
Наиболее часто используется именно в качестве поисковой системы, но возможно и
его применение в качестве персистентного NoSQL-хранилища. Имеется API для
работы с распространенными языками программирования. Сам Elasticsearch написан
на Java и распространяется свободно на условиях Apache License. Используется в
Wikimedia, Mozilla, Foursquare, Etsy, SoundCloud и GitHub.

● Sphinx. Простой, быстрый, легкий, используется в связке с базовый данных,


поиск по русскому/английскому тексту, wildcard поиск.
● Solr. Большой, мощный, выступает как хранилище, миллион функций, сделать
можно практически все, есть неточный поиск и возможность масштабироваться
из коробке.
● Elastic. Не только поиск и хранилище, а и другие инструменты (визуализация,
сборщик логов, система шифрования и т.п.). Умеет масштабироваться и
позволяет выполнять выборки очень сложной формы, что делает это хорошим
вариантов для аналитической платформы. Поддерживает репликацию, имеет
rest api, триггеры и хранимые процедуры. Поддерживает типы и не имеет
схемы. Требует Java.

Как обновить «Эластик», синхронизировать его с базой?

Разово и делать переодически, либо инкрементно менять индекс при обновлении


данных в основном хранилище.

способы автоматического обновления:

● elasticsearch-jdbc (jdbc river)


● logstash-input-jdbc
● Databus for MySQL
● Точечно обновлять индекс при обновлении сущностей

Точечное обновление:
● Как только обновление / обновления происходят в событии публикации /
событиях в очереди JMS/AMQP/Database / очереди файловой системы/Amazon
SQS и т. д. либо полный продукт, либо основной идентификатор объекта(я бы
рекомендовал просто ID)
● Затем потребитель очереди должен вызвать веб-службу, чтобы получить
полный объект, если только первичный ID помещен в очередь, или просто взять
сам объект и отправить соответствующие изменения в базу данных Elastic
search/NoSQL.

Отличие фабрики от билдера

Главное отличие от «фабрики» — это то, что она используется, когда создание
занимает один шаг, а «строитель» применяется при множестве шагов.

Можно ли через PDO вернуть объекты заданного класса

Можно, через PDO::FETCH_CLASS, PDO::FETCH_INTO

AUTO_INCREMENT vs UUID

Преимущества:

● Вы можете генерировать UUID везде


● Это означает, что вы можете создавать записи без подключения к базе данных
● UUID уникальны для разных таблиц, баз данных, систем
● Это позволяет легко объединять записи из разных таблиц, баз данных
● UUIDs делают репликацию более простой.
● Вы можете меньше беспокоиться о раскрытии бизнес-информации, если кто-то
будет перебирать идентификаторы в вашем api.

Недостатки:

● Использует больше памяти и дискового пространства, индексные таблицы


становятся больше. Но кого это волнует сегодня?
● Медленнее для SELECT с большими таблицами. Но возможны оптимизации
● Может быть намного медленнее для INSERT
● Потребуется больше времени для пересчета индекса, может быть серьезной
проблемой
● Более сложным для отладки из-за отсутствия порядка вставки Но вы можете
добавить колонку DATETIME (микросекунды) 'create_on' и использовать это для
сортировки.

Отличие unset() от == null


первый убивает саму переменную и данные, второй убивает только данные, а
переменную оставляется

SOAP vs REST
SOAP — это формат протокола, основанный на XML, тогда как REST — это
архитектурный подход.

REST и SOAP на самом деле не сопоставимы. REST — это архитектурный стиль.


SOAP — это формат обмена сообщениями. Давайте сравним популярные реализации
стилей REST и SOAP.

● Пример реализации RESTful: JSON через HTTP


● Пример реализации SOAP: XML поверх SOAP через HTTP

На верхнем уровне SOAP ограничивает структуры ваших сообщений, тогда как REST
— это архитектурный подход, ориентированный на использование HTTP в качестве
транспортного протокола.

Специфика SOAP — это формат обмена данными. С SOAP это всегда SOAP-XML,
который представляет собой XML, включающий:
● — Envelope (конверт) – корневой элемент, который определяет сообщение и
пространство имен, использованное в документе,
● — Header (заголовок) – содержит атрибуты сообщения, например: информация
о безопасности или о сетевой маршрутизации,
● — Body (тело) – содержит сообщение, которым обмениваются приложения,
● — Fault – необязательный элемент, который предоставляет информацию об
ошибках, которые произошли при обработке сообщений. И запрос, и ответ
должны соответствовать структуре SOAP.

Специфика REST — использование HTTP в качестве транспортного протокола. Он


подразумевает наилучшее использование функций, предоставляемых HTTP — методы
запросов, заголовки запросов, ответы, заголовки ответов и т. д.

● SOAP использует WSDL (Web Services Description Language) — язык описания


веб-сервисов и доступа к ним, основанный на языке XML.
● REST не имеет стандартного языка определения сервиса. Несмотря на то, что
WADL был одним из первых предложенных стандартов, он не очень популярен.
Более популярно использование Swagger или Open API.
● REST обычно использует JSON, который легче анализировать и обрабатывать.
В дополнение к этому, REST не требует наличия определения службы для
предоставления веб-службы.
● Однако в случае SOAP вам необходимо определить свой сервис с
использованием WSDL, и при обработке и анализе сообщений SOAP-XML
возникают большие накладные расходы.

b-tree и хеш индекс


Хеш индекс лучше со вставками, так как b-tree дорого перестраивать.

OWASP

OWASP (расшифровывается как Open Web Application Security Project) — это


онлайн-сообщество, которое выпускает статьи на тему безопасности веб-приложений,
а также документацию, различные инструменты и технологии.

10 основных уязвимостей OWASP 2020 года:

● Инъекционные атаки (Injections)


● Нарушенная аутентификация (Broken Authentication)
● Незащищённость критичных данных (Sensitive Data Exposure)
● Внешние объекты XML (XXE) (XML External Entities (XXE))
● Нарушение контроля доступа (Broken Access control)
● Небезопасная конфигурация (Security misconfigurations)
● Межсайтовый скриптинг (XSS) (Cross Site Scripting (XSS))
● Небезопасная десериализация (Insecure Deserialization)
● Использование компонентов с известными уязвимостями (Using Components
with known vulnerabilities)
● Неэффективный мониторинг (Insufficient logging and monitoring)

Зачем нужен composer.lock

Он содержит конкретные версии библиотек и версии их зависимостей, несколько


разных установок композера могут установить различные версии зависимостей
зависимостей. Из-за этого могут появиться трудно воспроизводимые баги. Еще он
хорош для CI/CD, так как зависимости при деплое будут устанавливаться быстрее,
если есть composer.lock.

Найти терминальные узлы sql

ID PARENT_ID

1 NULL

2 1

3 1

4 3

5 4

Вариант с подзапросом:

SELECT `id` FROM `tree` WHERE `id` NOT IN (SELECT `parent_id`


FROM `tree` WHERE `parent_id` IS NOT NULL)

Применение индексов

Существует таблица somename с колонками id,number,status,text

id — pk

number — любое число(могут повторяться)

text - текст
status — статусы от 1 до 10

Существуют индексы:

idx_1 по колонке number,

idx_2 по колонке text,

idx_3 по колонке status,

idx_4 составной индекс по колонкам: number, status

Idx_5 составной индекс по колонкам: text,status

Рассказать какой будет выбран индекс и почему.

1 Select * from somename where status=1 - применит индекс idx_3

2 Select * from somename where status>5 - не применит никакой индекс

3 Select * from somename where text like "%test" - не применит никакой индекс

4 Select * from somename where text like "test%" and status=2 - применит idx_2

5 Select * from somename where text like “%test" and status=2 - применит idx_3

6 Select * from somename where status=1 and number=1 - применит idx_1

7 Select * from somename where number>1000 and status=2 - применит idx_1 + where
8 Select * from somename where status>5 and number=1 - применит idx_1

9 Select * from somename where number>1000 and status>5 - частично применит idx_1

1 Select * from somename where number=1 or status=2 - применит объединенный


0 индекс idx_1,idx_3

Вам также может понравиться