Найти в Дзене
Квант

Вопросы и ответы на собеседование бэкэнд программиста

Обновляемый список часто встречающихся и заковыристых вопросов на собеседовании чтобы быстро освежить память. Можете добавлять свои варианты в комментариях. ООП (Объекто-ориентированное программирование) Как реализуется ООП? Какой тип наследования в PHP? class Dog extends Animal interface Flying extends Moving, Transporting class Dog implements Flying, Barking П.С.: тимлид в Сбере путает множественное наследование интерфейсов и имплементацию классов от них, поэтому надо самому превентивно уточнять что вы имеете в виду. Различия в наследовании в Python 2 и Python3? В Python 2 есть два типа классов: В Python 3 есть только новые классы. Везде используется C3. Поиск в глубину (англ. depth-first search, DFS) – это рекурсивный алгоритм обхода вершин графа. Он начинается с корня (выбирая какой-то произвольный узел в качестве корня в случае Graph) и исследует как можно дальше каждую ветвь, прежде чем вернуться. Алгоритм C3 (Си Три) - детерминированный порядок поиска методов (MRO). Этот порядо
Оглавление
SQL Joins
SQL Joins

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

ООП (Объекто-ориентированное программирование)

Как реализуется ООП?

  1. Наследование: это механизм, который позволяет создавать классы на основе других классов, перенимая их свойства и методы. Наследование помогает избежать дублирования кода и обеспечивает полиморфизм
  2. Полиморфизм: способность объектов разных классов обрабатываться одинаково. Объекты могут иметь несколько реализаций одного и того же метода. Использование одного имени для методов в разных классах: DOC.open(), PDF.open(). Перегрузка - параметрический полиморфизм func(int a), func(float a).
  3. Инкапсуляция: сокрытие данных (Модификаторы доступа: public, protected, private). Это помогает обеспечить безопасность данных, уменьшает возможность ошибок и упрощает поддержку программы.
  4. Абстракция: объекты скрывают детали реализации и представляют только интерфейс для взаимодействия с ними. Абстрактные классы и интерфейсы позволяют создавать новые объекты, которые могут быть использованы в различных контекстах без необходимости знать их внутреннюю структуру.
  5. Агрегация: методика создания нового класса из уже существующих классов путём их включения. (Пример: профессора — факультеты, профессора остаются жить после разрушения факультета)
  6. Композиция: агрегирование по значению, более строгий вариант агрегирования, когда включаемый объект может существовать только как часть контейнера. Если контейнер будет уничтожен, то и включённый объект тоже будет уничтожен. (Пример: университет — факультеты, факультеты без университета погибают.)
  7. Модульность: объекты должны быть разделены на модули, чтобы обеспечить их гибкость и модульность. Модульность позволяет упростить поддержку программы, уменьшить ее сложность и увеличить ее гибкость.
  8. Итеративность: объекты должны иметь возможность повторного использования кода.
  9. Параллелизм: объекты должны работать параллельно, чтобы увеличить производительность. Параллельность может быть достигнута с помощью многопоточности или асинхронного программирования.
  10. Рефлексия: объекты могут автоматически определять свои свойства и методы во время выполнения программы. Рефлексивные методы позволяют объектам взаимодействовать с другими объектами, не зная их точного типа.
  11. Тестирование: объекты должны тестироваться перед использованием.

Какой тип наследования в PHP?

  • Для классов - одиночное.
  • Для интерфейсов - множественное.
  • Классы могут реализовывать (имплементировать) несколько интерфейсов.
class Dog extends Animal
interface Flying extends Moving, Transporting
class Dog implements Flying, Barking

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

Различия в наследовании в Python 2 и Python3?

В Python 2 есть два типа классов:

  • Старые. Без указания родительского класса или не object. Глубокий поиск в глубину (DFS), который приводит к дублированию вызовов и несогласованности. Надо использовать super().
  • Новые. Наследуются от object. Поиск С3 (в ширину), который гарантирует линеаризацию иерархии наследования и устраняет дублирование вызовов. Не обязательно использовать super() и self.

В Python 3 есть только новые классы. Везде используется C3.

Поиск в глубину (англ. depth-first search, DFS) – это рекурсивный алгоритм обхода вершин графа. Он начинается с корня (выбирая какой-то произвольный узел в качестве корня в случае Graph) и исследует как можно дальше каждую ветвь, прежде чем вернуться.

Алгоритм C3 (Си Три) - детерминированный порядок поиска методов (MRO). Этот порядок также называется линеаризацией класса.

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

class X(object): pass

class Y(object): pass
class A(X, Y): pass
class B(Y, X): pass
class C(A, B): pass
linearization(B) = [B, Y, X, object]
linearization(C) = error, аннигиляция A и B.

Анонимная функция?

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

$result = array_map(function($number) {
return $number * 2;
}, [1, 2, 3]);

print_r($result);

Замыкание?

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

Замыкание (closure) - это функция, которая запоминает своё окружение. Окружение функции состоит из тех переменных, которые были определены в момент её создания. Эти переменные могут быть доступны внутри функции, даже если она вызывается в другом месте и в другое время.

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

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

function makeAdder($x) {
return function($y) use ($x) {
return $x + $y;
};
}

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

$addTo5 = makeAdder(5); // создаем замыкание, которое дает нам функцию для добавления 5
echo $addTo5(3); // выводит 8, так как 5+3=8
echo $addTo5(10); // выводит 15, так как предыдущее значение 5 было сохранено в замыкании

$addTo10 = makeAdder(10); // создаем другое замыкание для добавления 10
echo $addTo10(3); // выводит 13, так как 10+3=13

В этом примере makeAdder() возвращает анонимную функцию, которая имеет доступ к переменной $x, определенной внутри makeAdder(). Мы сохраняем эту функцию в $addTo5 и можем использовать ее для добавления чисел к 5. Мы также создаем второе замыкание в $addTo10, которое использует переменную $x, установленную на 10.

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

Связность и зацепление. GRASP.

Закон Деметры — Википедия
GRASP — Википедия
Зацепление (программирование) — Википедия
Связность (программирование) — Википедия

Domain Driven Development (DDD)

Domain Driven Development (DDD) или Разработка, Ориентированная на Домен - это подход к разработке программного обеспечения, который фокусируется на предметной области (domain) бизнеса. Это означает, что разработчики должны сосредоточиться на понимании логики бизнеса, его процессов и правил, а не только на реализации технических решений.

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

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

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

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

Что можно узнать о Domain Driven Design за 10 минут?

Сервисы

Не должны сохранять состояние.

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

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

Data Transfer Object (DTO)

DTO в языке PHP: примеры для начинающих

(Data Transfer Object, DTO) - это объект, который используется для передачи данных между разными слоями приложения или между разными микросервисами. Основная цель DTO - передать только те данные, которые действительно нужны для выполнения операции, и избежать передачи ненужных данных.

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

DTO также могут использоваться для маппинга данных из структур данных одного формата в другой, например, из JSON в POJO.

Value Object (VO)

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

SOLID

  • S - Single responsibility. Класс отвечает за что-то одно.
  • O - Open-closed (class). Классы открыты для расширения, но закрыты для изменения.
  • L - Liskov substitution. Принцип подстановки. (JsonResponce => Responce)
  • I - Interface segregation. Много интерфейсов лучше.
  • D - Dependency inversion. Инверсия зависимостей. (Класс подключения к БД не должен зависить от класса корзины).

YAGNI

«You aren't gonna need it», «Вам это не понадобится».

Не плодить сущности.

KISS

«Keep it simple, stupid»

«Делай проще, тупица»

Базы данных

Какой по умолчанию Join?

Inner Join

Left Join и Right Join?

Left join возвращает все строки из левой таблицы и совпадающие строки из правой таблицы. Если соответствующей записи нет в правой таблице, то правая часть записи будет заполнена значениями NULL.

SELECT TableA.id, TableA.name, TableB.city
FROM TableA
LEFT JOIN TableB
ON TableA.id = TableB.id;

Сколько столбцов будет в результате Join?

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

A + B - intersection(A,B)
[1,2,3,4] + [3,4,5,6,7,8] = [1,2, 3,4, 3,4, 5,6,7,8]
[1,2,3,4] + [3,4,5,6,7,8] - [3,4]= [1,2,3,4,5,6,7,8]
4 + 6 - 2 = 8

При left join количество столбцов в результирующей таблице будет равно сумме столбцов в обеих таблицах. Однако, если в обеих таблицах есть столбцы с одинаковыми именами, то они будут объединены в один столбец при left join. В этом случае количество столбцов в результирующей таблице будет меньше полной суммы. Например, если в обеих таблицах есть столбец id, то при left join он будет одним столбцом, а не двумя.

Почему после UPDATE строка становится на последнее место?

После выполнения оператора UPDATE в SQL строка не обязательно становится на последнее место. Было физическое перемещение на диске, а также это зависит от обработки страниц памяти в оперативной памяти.

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

Уровень изолированности транзакций — Википедия

CAP-теорема

Теорема CAP — Википедия

Индексы

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

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

Преимущества использования индексов:

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

Недостатки использования индексов:

- Необходимость дополнительной памяти для хранения индексов
- Дополнительная нагрузка на сервер базы данных при обновлении таблицы
- Увеличение времени на выполнение операций с таблицей при изменении индексов

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

В индексах баз данных могут быть следующие структуры:

  • B-дерево (B-tree) - наиболее распространенная структура индекса, которая позволяет быстро находить нужную запись.
  • Хеш-таблица (hash table) - структура, основанная на хешировании значений ключей.
  • Список (list) - простая структура данных, которая содержит ссылки на записи в порядке их следования.
  • R-дерево (R-tree) - структура, используемая для индексирования гео-данных, таких как точки или линии.
  • K-D-дерево (k-dimensional tree) - специальная структура индекса, используемая для поиска в многомерных пространствах.
  • Bitmap-индекс (bitmap index) - структура, используюется для индексирования бинарных данных, например, флагов или статусов.
  • Инвертированный индекс (inverted index) - структура, используется для полнотекстового поиска в текстовых данных, где каждый термин указывает на соответствующие документы.

Сети

Сетевая модель OSI — Википедия

HTTP — Википедия

REST — Википедия
SOAP — Википедия

Форматы данных

Protocol Buffers — Википедия
JSON — Википедия
XML — Википедия

Пакетные менеджеры

Composer

PHAR

Всё PHP приложение помещается в ZIP архив.

$phar = new Phar('myphar.phar');
$pgz = $phar->convertToExecutable(Phar::TAR, Phar::GZ); // makes myphar.phar.tar.gz

include 'phar://myphar.phar/index.php';

PECL

PHP Extension Community Library.

Репозиторий сообщества для расширений PHP.

PEAR

PHP Extension and Application Repository.

Репозиторий для расширений и приложений PHP.

PIP

The Python Package Installer

Тестирование

Виды тестов: модульное (юнит), функциональные, интеграционные, системные тесты?

По цели тестирования можно выделить следующие виды:

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

По уровню тестирования можно выделить следующие виды:

  • Модульное (юнит) тестирование - проверка отдельных модулей или функций кода на корректность и соответствие спецификации.
  • Интеграционное тестирование - проверка взаимодействия нескольких модулей или компонентов приложения или системы.
  • Системное тестирование - проверка работы всего приложения или системы в целом на соответствие требованиям.
  • Приёмочное тестирование - проверка удовлетворения потребностей и ожиданий пользователей и заказчика.

По способу доступа к коду или архитектуре можно выделить следующие виды:

  • Тестирование “чёрного ящика” - проверка внешнего поведения приложения или системы без знания внутреннего устройства.
  • Тестирование “белого ящика” - проверка внутренней структуры и логики приложения или системы с знанием кода и архитектуры.
  • Тестирование “серого ящика” - комбинация тестирования “чёрного” и “белого” ящиков с частичным знанием кода и архитектуры.

Различия тестов?

  • Юнит тесты проверяют работу отдельных модулей или функций кода на корректность и соответствие спецификации. Юнит тесты обычно пишутся разработчиками, используют специальные инструменты и фреймворки (например, PHPUnit, PyUnit, NUnit, xUnit, MSTest и т.д.) и запускаются автоматически при каждой сборке или изменении кода. Юнит тесты помогают обнаруживать ошибки на ранних стадиях разработки, улучшать качество кода, снижать связность и упрощать рефакторинг.
  • Функциональные тесты проверяют работу всего приложения или его частей с точки зрения пользователя или бизнес-требований. Функциональные тесты обычно пишутся тестировщиками, используют ручные или автоматизированные методы (например, Selenium, Cucumber, SpecFlow и т.д.) и запускаются периодически или перед релизом. Функциональные тесты помогают убедиться, что приложение выполняет свои основные функции, удовлетворяет потребностям пользователей и соответствует ожиданиям заказчика.
  • Регрессионное тесты - это вид тестирования, который направлен на обнаружение ошибок в уже протестированных участках исходного кода. Регрессионные ошибки - это ошибки, которые появляются после внесения изменений в код или окружение приложения или системы. Регрессионное тестирование помогает убедиться, что новая версия приложения или системы не содержит дефектов в областях, не подвергавшихся изменениям. Регрессионное тестирование обычно проводится после исправления ошибок, добавления новых функций, обновления версий библиотек или компонентов, переноса на новые сервера и т.д.. Регрессионное тестирование может включать повторные прогоны предыдущих тестов или проверки новых сценариев, связанных с изменениями.
  • Интеграционные тесты - это вид тестирования, в котором проверяется работа нескольких компонентов приложения вместе. Интеграционные тесты проводятся после юнит тестов и перед системными тестами. Цель интеграционных тестов - убедиться, что компоненты согласованно взаимодействуют друг с другом и с внешними ресурсами, такими как базы данных, файловые системы, сети и т.д.. Интеграционные тесты обычно требуют больше времени и ресурсов, чем юнит тесты, поэтому они запускаются реже и только для наиболее важных сценариев. Интеграционные тесты также сложнее писать и поддерживать, так как они зависят от состояния и настроек внешних компонентов.
  • Системные тесты - это вид тестирования, в котором проверяется работа всего приложения или системы в целом на соответствие исходным требованиям. Системные тесты проводятся после интеграционных тестов и перед приёмочными тестами. Цель системных тестов - убедиться, что приложение или система выполняет свои основные функции, удовлетворяет потребностям пользователей и заказчика и работает корректно в реальном окружении. Системные тесты обычно выполняются методом “чёрного ящика”, то есть без знания внутреннего устройства приложения или системы. Системные тесты могут включать различные типы тестов, такие как функциональные, нефункциональные, совместимости, безопасности, производительности и т.д.. Системные тесты требуют большого времени и ресурсов, поэтому они запускаются на финальных стадиях разработки или перед релизом.

Тестирование производительности?

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

Тестирование безопасности?

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

Тестирование безопасности включает в себя следующие аспекты:

  • Конфиденциальность - защита данных от разглашения непреднамеренным получателям.
  • Целостность - обеспечение точности и правильности данных при передаче и хранении.
  • Аутентификация - проверка и подтверждение личности пользователя.
  • Авторизация - определение прав и ролей доступа к ресурсам.
  • Доступность - обеспечение готовности и работоспособности системы по требованию.
  • Безотказность - гарантия непрерывности работы системы и ее восстановления после сбоев.

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

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

  • Тестирование на проникновение (penetration testing) - имитация реальной атаки на систему с целью выявить и эксплуатировать уязвимости.
  • Тестирование на уязвимости (vulnerability testing) - сканирование системы с помощью специальных инструментов для обнаружения известных уязвимостей.
  • Тестирование на отказоустойчивость (failover testing) - проверка способности системы переключаться на резервные ресурсы в случае сбоя основных.
  • Тестирование на соответствие (compliance testing) - проверка соответствия системы стандартам и нормативам безопасности.

"Mocking" в юнит тестировании?

mocking - пародирование

  • Заменитель базы данных
  • Заменитель для имитации ошибок
  • Заменитель REST API

Mocking в юнит тестировании - это процесс создания и использования тестовых двойников (mocks) для имитации поведения реальных объектов или зависимостей в тестируемом модуле. Mocks позволяют изолировать тестируемый модуль от внешних факторов и проверять его корректность. Например, если вы хотите протестировать класс, который использует провайдер данных из интернета, вы можете создать mock провайдера, который возвращает заранее заданные данные без реального http-запроса.

AAA в тестировании?

Arrange, Act, Assert - Подготовка, Действие, Проверка

"Arrow at ass" - стрела в задницу.

AAA в тестировании - это паттерн написания юнит-тестов, который состоит из трех фаз:

  • Arrange (подготовка) - в этой фазе вы создаете и настраиваете все необходимые объекты, данные и зависимости для теста.
  • Act (действие) - в этой фазе вы вызываете тестируемый метод или функцию и получаете результат его работы.
  • Assert (проверка) - в этой фазе вы проверяете, что результат соответствует ожиданиям, а также что не произошло никаких ошибок или исключений.

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

Системы контроля версий (Git)

Git — Википедия
Рабочий процесс Git | Atlassian Git Tutorial

Поведенческое интервью

Какие были конфликты на рабочем месте, стрессовые ситуации, как к вам относился директор?

Метод STAR - Situatioin, Task, Action, Result.

Необходимо придумать косяки и рассказать как вы их решали. Следует говорить "Я", а не "Мы",

Ситуация: Однажды была очень стрессовая ситуация. Упал продакшен. Клиенты были в ярости и грозили судебными исками. Директор был очень зол и грозился всех уволить.

Задача: Я стремился как можно скорее найти проблему и поднять обратно сервер к которому у меня не было доступа.

Действия: Я не нашёл проблему. Оказалось что на сервере стояли другие версии пакетов, чем те что использовались при разработке и тестировании.

Результат: Меня уволили. Я откатил новые изменения через git revert. Сервер поднялся обратно. Были сделаны выводы что надо использовать одинаковые версии пакетов везде. Я синхронизировал версии пакетов как в контейнере для разработчиков, так и в продакшене.

Кем вы видете себя через 5 лет?

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

Не следует говорить про менеджерские позиции.

Почему вы ушли с предыдущего места работы?

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

Проект был из США. В виду напряжённой политической обстановки они решили прекратить работу с Россией. В основом по причине невозможности проведения платежей через SWIFT. Некоторое время они ещё переводили оплату криптой, но были большие затраты из-за высокой коммиссии, также это было непрозрачно для их бухгалтерии.

Почему вы ушли с предыдущего места работы?

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

Компания работала с сотрудниками удалённо, но тут решила вернуть всех в офис. Мне было некомфортно переезжать из Бобруйска в Москву, т.к. зарплату при переезде они не поднимали до уровня московской, а платили местную в 30к. На такие деньги даже квартиру там не снимешь.

Почему вы хотите работать у нас?

Я хочу улучшить своё материальное положение.

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

Рекомендации по выбору галеры

По типу компании:

  • Продуктовая (меньше микроменеджмента, приоритет на качество, а не скорость, больше бюрократии)
  • Заказная, Аутсорс, Аутстафф, Веб-студия (задолбают микроменеджментом, кейлоггерами и скринерами экрана).

По городу:

  • Московская удалёнка (в целом адекватнее, построены процессы, белая ЗП и ТК)
  • Из любого другого города (будут кидать с оплатой, неоплачиваемые переработки и т.п.)

По цвету зарплаты:

  • Оформление по ТК, Белая ЗП.
  • Просто оформление по ТК == Серая ЗП. Будут кидки по зарплате.
  • Ничего не указано, либо ИП или Самозанятые (точно будет кидалово с оплатой).

По размеру компании:

  • МЯСО (Мейл.ру, Яндекс, Сбер, Озон) - норм, сложно попасть. 5 этапов собесов с алгоритмическими интервью у белой доски. В офисе опенспейсы, людей как селёдок в бочке.
  • Средние на слуху (Банки, Опсосы, Екомы) - легче попасть, сравнительно адекватно.
  • Веб-студии - подойдёт для старта карьеры на полгода.
  • Стартапы - не построены процессы, переработки, нет денег на зарплату, не оформляют трудовые договоры, быстро увольняют без выплаты зарплаты.

PHP

Отвечаем на 100+ вопросов собеседования для PHP программиста.pdf

Вопросы и ответы PHP (habr)

Андрей Шевченко - PHP в вопросах и ответах (2012)

Основы Backend разарботки (web протоколы и т.п.)

Python

Вопросы и ответы по Python (база)

Вопросы и ответы по Python (побольше)

Основы Backend разарботки (web протоколы и т.п.)

JAVA

Вопросы и ответы по JAVA