С
logo
0
читателей
Сурен Хоренян | Программирование  Образовательные ролики про программированию и алгоритмам
О проекте Просмотр Уровни подписки Фильтры Статистика Обновления проекта Поделиться Метки
Все проекты
О проекте
Привет! Меня зовут Сурен, я Senior Python Developer.
Онлайн-образованием я занимаюсь с 2018 года. Люблю Python, алгоритмы, базы данных. Рад поделиться с вами опытом и знаниями.
Все мои ресурсы: https://taplink.cc/mahenzon
Публикации, доступные бесплатно
Уровни подписки
Единоразовый платёж

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

Помочь проекту
O(n^2) 210₽ месяц 2 142₽ год
(-15%)
При подписке на год для вас действует 15% скидка. 15% основная скидка и 0% доп. скидка за ваш уровень на проекте Сурен Хоренян | Программирование
Доступны сообщения

Это хороший способ решить задачу. Ваша помощь обеспечит оплату одного превью!

Оформить подписку
O(n * log(n)) 500₽ месяц 4 920₽ год
(-18%)
При подписке на год для вас действует 18% скидка. 18% основная скидка и 0% доп. скидка за ваш уровень на проекте Сурен Хоренян | Программирование
Доступны сообщения

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

Оформить подписку
O(n) 990₽ месяц 9 504₽ год
(-20%)
При подписке на год для вас действует 20% скидка. 20% основная скидка и 0% доп. скидка за ваш уровень на проекте Сурен Хоренян | Программирование
Доступны сообщения

Показав на собеседовании решение с линейной сложностью вы точно пройдёте дальше. За два месяца подписки вы поможете с монтажом одного видео!

Оформить подписку
O(log(n)) 1 950₽ месяц 18 252₽ год
(-22%)
При подписке на год для вас действует 22% скидка. 22% основная скидка и 0% доп. скидка за ваш уровень на проекте Сурен Хоренян | Программирование
Доступны сообщения

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

Оформить подписку
O(1) 3 200₽ месяц 28 800₽ год
(-25%)
При подписке на год для вас действует 25% скидка. 25% основная скидка и 0% доп. скидка за ваш уровень на проекте Сурен Хоренян | Программирование
Доступны сообщения

Круче тебя и быть не может. Ты как словарь в Python - на тебе всё держится! Спасибо за обеспечение полного цикла производства одного видео в месяц! Я выражу тебе личную благодарность в этом видео.

Оформить подписку
Фильтры
Статистика
Обновления проекта
Контакты
Поделиться
Метки
Читать: 3+ мин
С
logo
Сурен Хоренян | Программирование

Как решать LeetCode задачи

Как ‎решать‏ ‎LeetCode ‎задачи


Отвечаю ‎на ‎вопрос ‎«А‏ ‎как ‎решать‏ ‎задачи‏ ‎на ‎литкоде?», ‎который‏ ‎часто ‎встречаю‏ ‎в ‎разных ‎формулировках ‎у‏ ‎себя‏ ‎в ‎комментариях.


Сразу‏ ‎обозначу, ‎что‏ ‎чтобы ‎научиться ‎решать ‎литкод ‎задачи,‏ ‎нужно‏ ‎решать ‎литкод‏ ‎задачи. ‎Некоторые‏ ‎решают ‎литкод ‎задачи ‎чтобы ‎подготовиться‏ ‎к‏ ‎собеседованию.‏ ‎Некоторые ‎просто‏ ‎для ‎расширения‏ ‎кругозора, ‎для‏ ‎набора‏ ‎общего ‎опыта‏ ‎(я ‎для ‎этого ‎решаю).

Если ‎вы‏ ‎думаете, ‎что‏ ‎научившись‏ ‎решать ‎литкод ‎задачи‏ ‎вы ‎станете‏ ‎классным ‎прогаммистом, ‎скажу, ‎что‏ ‎это‏ ‎так ‎не‏ ‎работает. ‎Не‏ ‎станете.


Решение ‎задачек ‎на ‎литкоде ‎это‏ ‎заучивание‏ ‎паттернов. ‎Если‏ ‎вы ‎пробовали‏ ‎решать ‎дейли ‎задачки, ‎то ‎могли‏ ‎заметить,‏ ‎что‏ ‎одну-две ‎недели‏ ‎подряд ‎идёт‏ ‎примерно ‎одна‏ ‎и‏ ‎та ‎же‏ ‎тема, ‎просто ‎под ‎разными ‎соусами.


Выбирайте‏ ‎популярные ‎задачи,‏ ‎у‏ ‎которых ‎высокий ‎процент‏ ‎принятия, ‎начинайте‏ ‎с ‎Easy ‎задач. ‎Не‏ ‎на‏ ‎каждом ‎собесе‏ ‎спросят ‎Medium,‏ ‎а ‎Hard ‎вообще ‎нужен ‎только‏ ‎чтобы‏ ‎потешить ‎своё‏ ‎самолюбие.


Итак, ‎как‏ ‎решать ‎задачи ‎на ‎LeetCode


Открываете ‎задачку.‏ ‎Читаете‏ ‎условие,‏ ‎выводите ‎для‏ ‎себя ‎границы‏ ‎задачи. ‎Я‏ ‎в‏ ‎каждом ‎ролике‏ ‎начинаю ‎с ‎чтения ‎условий ‎задачи,‏ ‎объясняю ‎своими‏ ‎словами,‏ ‎что ‎имеется ‎в‏ ‎виду.


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


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


Поэтому ‎переходите‏ ‎к ‎поиску ‎разборов ‎решения. ‎Нужно‏ ‎не ‎просто‏ ‎готовое‏ ‎решение, ‎а ‎целый‏ ‎разбор ‎с‏ ‎объяснением, ‎почему ‎именно ‎так.‏ ‎Текстовый‏ ‎разбор, ‎видео‏ ‎с ‎решением‏ ‎(например ‎как ‎у ‎меня) ‎—‏ ‎на‏ ‎ваше ‎усмотрение.‏ ‎После ‎просмотра‏ ‎объяснения ‎попробуйте ‎решить ‎задачу ‎самостоятельно.‏ ‎Вы‏ ‎уже‏ ‎знаете ‎суть,‏ ‎понимаете ‎решение.‏ ‎Если ‎не‏ ‎поняли,‏ ‎то ‎посмотрите‏ ‎другой ‎разбор. ‎И ‎переходите ‎к‏ ‎коду.


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


Если ‎не‏ ‎удаётся‏ ‎воспроизвести,‏ ‎пересмотрите ‎разбор‏ ‎и ‎попробуйте‏ ‎ещё ‎раз.


Всё‏ ‎ещё‏ ‎не ‎можете‏ ‎понять? ‎Это ‎не ‎повод ‎расстраиваться.‏ ‎Таблицу ‎умножения‏ ‎мы‏ ‎тоже ‎когда-то ‎заучивали.‏ ‎Нет ‎ничего‏ ‎страшного ‎в ‎том, ‎что‏ ‎вы‏ ‎не ‎поняли‏ ‎суть, ‎но‏ ‎запомнили ‎решение. ‎Из ‎этих ‎кирпичиков‏ ‎потом‏ ‎строится ‎более‏ ‎сложное ‎решение.‏ ‎Перепишите ‎весь ‎код ‎вручную ‎(никакой‏ ‎копипасты!),‏ ‎но‏ ‎**все ‎переменные**‏ ‎называйте ‎иначе,‏ ‎как-то ‎по-своему.‏ ‎Это‏ ‎заставит ‎вас‏ ‎следить ‎за ‎сутью ‎кода, ‎а‏ ‎не ‎переписывать‏ ‎вслепую,‏ ‎вам ‎придётся ‎следить‏ ‎за ‎сущностями,‏ ‎которыми ‎вы ‎оперируете.


Если ‎полученный‏ ‎код‏ ‎не ‎работает,‏ ‎сравните ‎через‏ ‎любой ‎diff ‎checker ‎(в ‎PyCharm‏ ‎это‏ ‎compare ‎with‏ ‎clipboard). ‎Возьмите‏ ‎готовое ‎решение, ‎поменяйте ‎там ‎переменные‏ ‎на‏ ‎свои,‏ ‎сравните, ‎где‏ ‎вы ‎перепутали‏ ‎оператор, ‎добавили‏ ‎лишний‏ ‎отступ, ‎или‏ ‎обратились ‎не ‎к ‎той ‎сущности.


После‏ ‎того, ‎как‏ ‎удалось‏ ‎подготовить ‎рабочее ‎решение,‏ ‎и ‎литкод‏ ‎показал ‎вам ‎случайные ‎числа,‏ ‎поставьте‏ ‎себе ‎напоминание‏ ‎на ‎завтра,‏ ‎чтобы ‎вы ‎решили ‎эту ‎задачку‏ ‎снова.‏ ‎Через ‎неделю‏ ‎вернитесь ‎к‏ ‎этой ‎задаче ‎вновь. ‎После ‎решения‏ ‎вернитесь‏ ‎к‏ ‎этой ‎задаче‏ ‎ещё ‎через‏ ‎месяц.

Так ‎вы‏ ‎запомните‏ ‎суть ‎и‏ ‎решение ‎этой ‎задачи.


Ну, ‎это ‎всё‏ ‎актуально, ‎если‏ ‎вам‏ ‎действительно ‎хочется ‎разобраться‏ ‎и ‎научиться.

Через‏ ‎сотню-другую ‎задач ‎вы ‎начнёте‏ ‎замечать‏ ‎повторяющиеся ‎модели‏ ‎/ ‎структуры‏ ‎задач, ‎и ‎будет ‎легче.


Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Секрет в том, что секрета нет

Когда ‎я‏ ‎только ‎начинал ‎программировать ‎(писать ‎сайты,‏ ‎создавать ‎приложения‏ ‎с‏ ‎графическим ‎интерфейсом), ‎мне‏ ‎казалось, ‎что‏ ‎есть ‎какие-то ‎секреты, ‎тайны,‏ ‎которые‏ ‎скрывают ‎настоящие‏ ‎программисты. ‎Как‏ ‎делают ‎сборку ‎приложений? ‎Как ‎эти‏ ‎приложения‏ ‎запускают? ‎А‏ ‎как ‎обрабатывают‏ ‎пользовательские ‎данные? ‎Как ‎реализуют ‎уровни‏ ‎доступа?

Оказалось,‏ ‎что‏ ‎никаких ‎секретов‏ ‎нет. ‎Делают‏ ‎как ‎делают.‏ ‎Чаще‏ ‎всего ‎делают‏ ‎как ‎попало. ‎Потому ‎что ‎самое‏ ‎главное, ‎чтобы‏ ‎хоть‏ ‎как-то ‎работало. ‎А‏ ‎какой ‎ужас‏ ‎творится ‎под ‎капотом. ‎лучше‏ ‎бы‏ ‎вот ‎это‏ ‎реально ‎никому‏ ‎не ‎показывали.

Да, ‎есть ‎крутые ‎спецы,‏ ‎которые‏ ‎умеют ‎построить‏ ‎технологичные ‎и‏ ‎понятные ‎системы. ‎Но ‎они ‎существуют‏ ‎где-то‏ ‎там,‏ ‎в ‎другом‏ ‎месте. ‎А‏ ‎работать ‎придётся‏ ‎с‏ ‎тем, ‎что‏ ‎есть. ‎С ‎тем, ‎что ‎выполняет‏ ‎бизнес-требования.

Читать: 2+ мин
С
logo
Сурен Хоренян | Программирование

Зачем PlantUML, когда есть С4?

PlantUML

Если ‎вы‏ ‎хоть ‎чуть-чуть ‎в ‎сфере ‎ИТ,‏ ‎вы ‎точно‏ ‎встречали‏ ‎PlantUML ‎диаграммы. ‎Это‏ ‎такие ‎схемки‏ ‎с ‎пошаговым ‎описанием ‎действий‏ ‎в‏ ‎системе, ‎или‏ ‎описанием ‎структуры‏ ‎проекта ‎(сервисы, ‎базы, ‎и ‎тд).‏ ‎Визуализация‏ ‎это, ‎конечно,‏ ‎прекрасно, ‎но‏ ‎хорошая ‎визуализация ‎ещё ‎лучше. ‎А‏ ‎PlantUML‏ ‎предоставляет‏ ‎хорошую ‎визуализацию‏ ‎только ‎для‏ ‎одного ‎уровня‏ ‎абстракции.


С4

В‏ ‎проекте ‎всегда‏ ‎можно ‎выделить ‎несколько ‎уровней ‎абстракции,‏ ‎и ‎именно‏ ‎про‏ ‎это ‎модель ‎C4.‏ ‎Четверка ‎в‏ ‎названии ‎означает ‎уровни:

1. Диаграмма ‎системы‏ ‎—‏ ‎что ‎приносит‏ ‎пользу ‎пользователю.‏ ‎Система ‎состоит ‎из ‎контейнеров.

2. Диаграмма ‎контейнера‏ ‎—‏ ‎наши ‎программистские‏ ‎сущности: ‎базы‏ ‎данных, ‎s3, ‎отдельные ‎приложения ‎и‏ ‎микросервисы,‏ ‎это‏ ‎всё ‎контейнеры.‏ ‎И ‎каждый‏ ‎контейнер ‎состоит‏ ‎из‏ ‎компонентов.

3. Диаграмма ‎компонента‏ ‎— ‎это ‎модули ‎ПО. ‎Например,‏ ‎микросервис ‎состоит‏ ‎из‏ ‎нескольких ‎компонентов: ‎СУБД,‏ ‎контейнер ‎с‏ ‎приложением, ‎веб-сервер.

4. Диаграмма ‎кода ‎—‏ ‎каждый‏ ‎компонент ‎как-то‏ ‎напрограммирован. ‎Вот‏ ‎тут ‎можно ‎сделать ‎описание ‎модулей‏ ‎и‏ ‎классов ‎(опускаться‏ ‎до ‎этого‏ ‎уровня ‎обычно ‎не ‎нужно).


Кто ‎кого?

Ещё‏ ‎есть‏ ‎правило,‏ ‎что ‎нужно‏ ‎указывать ‎направленность‏ ‎взаимодействия. ‎Например,‏ ‎код‏ ‎ходит ‎в‏ ‎базу ‎данных. ‎Да, ‎тут ‎сразу‏ ‎понятно, ‎кто‏ ‎к‏ ‎кому ‎обращается, ‎ведь‏ ‎БД ‎сама‏ ‎не ‎ходит ‎к ‎приложению.

Если‏ ‎взаимодействие‏ ‎с ‎API,‏ ‎то ‎указывать‏ ‎направленность ‎очень ‎важно: ‎мы ‎можем‏ ‎запрашивать‏ ‎данные ‎с‏ ‎внешнего ‎ресурса,‏ ‎а ‎также ‎ресурс ‎может ‎уведомлять‏ ‎наше‏ ‎приложение‏ ‎о ‎новом‏ ‎событии. ‎И‏ ‎при ‎указании‏ ‎направленности‏ ‎мы ‎ещё‏ ‎и ‎подписываем ‎стрелочку, ‎уточняем, ‎что‏ ‎именно ‎тут‏ ‎происходит.

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

PlantUML ‎всё‏ ‎ещё ‎актуален ‎для ‎Sequence ‎диаграмм‏ ‎—‏ ‎схем ‎с‏ ‎последовательностью ‎действий,‏ ‎например ‎«пользователь ‎запросил ‎А, ‎система‏ ‎вытащила‏ ‎данные‏ ‎из ‎B,‏ ‎перепроверила ‎через‏ ‎C ‎и‏ ‎отдала‏ ‎пользователю». ‎А‏ ‎вот ‎если ‎структура ‎системы ‎описана‏ ‎по ‎C4,‏ ‎то‏ ‎это ‎гораздо ‎понятнее.


Кстати,‏ ‎что ‎PlantUML,‏ ‎что ‎C4 ‎рисовать ‎руками‏ ‎не‏ ‎нужно, ‎используйте‏ ‎для ‎этого‏ ‎текстовый ‎формат: ‎его ‎легко ‎версионировать‏ ‎и‏ ‎распространять. ‎Есть‏ ‎свои ‎языки‏ ‎для ‎этого, ‎а ‎также ‎реализации‏ ‎на‏ ‎привычных‏ ‎нам ‎Python,‏ ‎JS ‎и‏ ‎тд.


Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Запиши пока не забыл

Как ‎только‏ ‎проскакивает ‎мысль ‎«надо ‎запомнить» ‎или‏ ‎«надо ‎не‏ ‎забыть»,‏ ‎я ‎тут ‎же‏ ‎записываю. ‎Всё‏ ‎что ‎«надо ‎не ‎забыть»‏ ‎забывается‏ ‎быстрее ‎всего.‏ ‎Надо ‎обязательно‏ ‎записать.

Это ‎помогает ‎разгрузить ‎память, ‎избавиться‏ ‎от‏ ‎лишней ‎информации,‏ ‎а ‎также‏ ‎освободить ‎место ‎для ‎новых ‎мыслей.‏ ‎К‏ ‎записанной‏ ‎идее ‎гораздо‏ ‎вернуться, ‎чем‏ ‎пытаться ‎её‏ ‎выудить‏ ‎из ‎памяти‏ ‎или ‎восстанавливать ‎тот ‎ход ‎мыслей,‏ ‎что ‎был‏ ‎час‏ ‎/ ‎день ‎/‏ ‎неделю ‎назад.

И‏ ‎наоборот, ‎это ‎хороший ‎способ‏ ‎что-то‏ ‎забыть. ‎Вот‏ ‎думаешь ‎«я‏ ‎бы ‎не ‎хотел ‎об ‎этом‏ ‎вспоминать»,‏ ‎и ‎вспоминаешь‏ ‎об ‎этом‏ ‎раз ‎за ‎разом. ‎А ‎стоит‏ ‎подумать‏ ‎«буду‏ ‎об ‎этом‏ ‎помнить», ‎и‏ ‎забываешь ‎в‏ ‎ближайшее‏ ‎время.


Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Качество подписчиков важнее количества

Вчера ‎в‏ ‎Телеграм ‎канале ‎случилась ‎первая ‎тысяча‏ ‎подписчиков.

У ‎меня‏ ‎лучшие‏ ‎подписчики. ‎Конечно, ‎у‏ ‎каждого ‎блогера‏ ‎именно ‎его ‎подписчики ‎самые‏ ‎лучшие.

Спасибо,‏ ‎что ‎читаете.‏ ‎Отдельное ‎спасибо‏ ‎всем, ‎кто ‎проявляет ‎активность: ‎ставит‏ ‎реакции,‏ ‎пишет ‎комментарии.

Например,‏ ‎этой ‎ночью‏ ‎успели ‎обсудить ‎математические ‎правила ‎по‏ ‎приоритетам‏ ‎операций,‏ ‎финансовые ‎инструменты‏ ‎(ипотеки, ‎вклады),‏ ‎так ‎ещё‏ ‎и‏ ‎успевали ‎отвечать‏ ‎на ‎вопросы ‎по ‎коду.

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

А‏ ‎кто‏ ‎считает, ‎что‏ ‎я ‎неправ,‏ ‎что ‎у ‎меня ‎лучшие ‎подписчики,‏ ‎можете‏ ‎отписываться,‏ ‎ведь ‎качество‏ ‎важнее ‎количества.

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Единственный глупый вопрос это незаданный вопрос

Не ‎начинайте‏ ‎с ‎«А ‎можно ‎глупый ‎вопрос?».‏ ‎Забудьте ‎такое‏ ‎сочетание‏ ‎слов, ‎это ‎глупый‏ ‎вопрос. ‎А‏ ‎самый ‎глупый ‎вопрос ‎тот,‏ ‎который‏ ‎вы ‎не‏ ‎задали. ‎Если‏ ‎вы ‎попали ‎в ‎чат ‎/‏ ‎сообщество‏ ‎снобов, ‎где‏ ‎вас ‎высмеивают‏ ‎за ‎ваши ‎вопросы, ‎ищите ‎другое‏ ‎место,‏ ‎где‏ ‎вам ‎подскажут.

При‏ ‎этом ‎важно‏ ‎уметь ‎задавать‏ ‎вопрос.‏ ‎Если ‎вы‏ ‎не ‎можете ‎описать ‎проблему, ‎сформулировать‏ ‎мысль, ‎то‏ ‎вам‏ ‎не ‎смогут ‎помочь.‏ ‎Помните ‎про‏ ‎непривет и ‎проблему ‎XY.

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Про синдром фронтендера

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

Бекендеру ‎(веб) ‎кажется, ‎что‏ ‎реальные‏ ‎программисты ‎это‏ ‎те ‎ребята,‏ ‎что ‎пишут ‎нативные ‎приложения ‎на‏ ‎плюсах.

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

А ‎одинэсники.‏ ‎они ‎просто‏ ‎счастливы.

Часто‏ ‎испытываете ‎синдром ‎фронтендера?

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Эффект сарая, или цена договариваемости (он же закон тривиальности)

Эффект ‎сарая,‏ ‎или ‎цена ‎договариваемости ‎(он ‎же‏ ‎закон ‎тривиальности)

В‏ ‎какой‏ ‎цвет ‎мне ‎покрасить‏ ‎сарай? ‎Или,‏ ‎может ‎быть, ‎вы ‎подскажете,‏ ‎какой‏ ‎тренажёр ‎установить‏ ‎во ‎дворе?‏ ‎Несложные ‎вопросы, ‎правда? ‎А ‎как‏ ‎сделать‏ ‎атомный ‎реактор?‏ ‎Сможете ‎подсказать?‏ ‎Тут ‎советов ‎будет ‎поменьше.

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

Паркинсон ‎сформулировал‏ ‎закон ‎тривиальности‏ ‎так: ‎«Время, ‎потраченное ‎на ‎обсуждение‏ ‎пункта,‏ ‎обратно‏ ‎пропорционально ‎рассматриваемой‏ ‎сумме». ‎Это‏ ‎всё ‎про‏ ‎то,‏ ‎что ‎людям‏ ‎легко ‎обсуждать ‎незначительные ‎решения, ‎но‏ ‎тяжело ‎принимать‏ ‎действительно‏ ‎важные.

Зачастую, ‎когда ‎людям‏ ‎дают ‎выбор,‏ ‎все ‎делают ‎по-своему, ‎если‏ ‎это‏ ‎какая-то ‎мелочь.‏ ‎Например, ‎на‏ ‎одном ‎проекте ‎я ‎встретил ‎целых‏ ‎три‏ ‎вида ‎пагинации‏ ‎между ‎разными‏ ‎API ‎ресурсами. ‎На ‎другом ‎проекте‏ ‎встретил‏ ‎несколько‏ ‎разных ‎базовых‏ ‎классов ‎для‏ ‎решения ‎одной‏ ‎задачи.‏ ‎И ‎это‏ ‎касается ‎не ‎только ‎программирования: ‎если‏ ‎соседям ‎предложить‏ ‎сделать‏ ‎улучшение ‎во ‎дворе‏ ‎(перестелить ‎газон,‏ ‎обновить ‎тренажёры), ‎люди ‎скорее‏ ‎просто‏ ‎откажутся, ‎чем‏ ‎смогут ‎договориться.‏ ‎Здесь ‎без ‎лица, ‎принимающего ‎решение,‏ ‎не‏ ‎обойтись.

Именно ‎поэтому‏ ‎так ‎сложно‏ ‎внедрять ‎новые ‎технологии ‎в ‎проект,‏ ‎особенно,‏ ‎если‏ ‎это ‎какие-то‏ ‎строгие ‎ограничения‏ ‎(см ‎ruff,‏ ‎black,‏ ‎radon, ‎etc),‏ ‎так ‎что ‎приходится ‎брать ‎всё‏ ‎в ‎свои‏ ‎руки,‏ ‎выстраивать ‎строгие ‎требования,‏ ‎а ‎потом‏ ‎сваливать ‎всё ‎на ‎бездушную‏ ‎машину.‏ ‎Не ‎нравится,‏ ‎что ‎линтер‏ ‎ругает ‎ваш ‎код? ‎Ну ‎извините,‏ ‎это‏ ‎вот ‎пайплайн‏ ‎так ‎работает,‏ ‎придётся ‎чинить ‎код, ‎что ‎поделать.

Точно‏ ‎также‏ ‎и‏ ‎про ‎строгие‏ ‎требования ‎к‏ ‎API. ‎Например,‏ ‎чтобы‏ ‎структура ‎запросов‏ ‎и ‎ответов ‎была ‎одинаковой ‎для‏ ‎всех ‎ресурсов.

Сделать‏ ‎своими‏ ‎силами ‎благоустройство ‎во‏ ‎дворе ‎чуть‏ ‎сложнее, ‎конечно, ‎если ‎большинство‏ ‎жильцов‏ ‎равнодушны ‎или‏ ‎против. ‎Но‏ ‎это ‎уже ‎совсем ‎другая ‎история.

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

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

Ленитесь ‎изобретать‏ ‎велосипеды. ‎Ленитесь ‎копипастить. ‎Если ‎вам‏ ‎лень ‎написать‏ ‎нормально‏ ‎и ‎поэтому ‎вы‏ ‎копипастите ‎—‏ ‎это ‎неправильная ‎лень. ‎Потому‏ ‎что‏ ‎программист ‎должен‏ ‎думать ‎наперёд.‏ ‎Если ‎вы ‎что-то ‎скопировали, ‎потом‏ ‎придётся‏ ‎копировать ‎снова.‏ ‎Вам ‎должно‏ ‎быть ‎лень ‎скопировать ‎снова, ‎лучше‏ ‎один‏ ‎раз‏ ‎сделать ‎нормально‏ ‎и ‎потом‏ ‎переиспользовать.

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Моя проблема с незнакомыми номерами

Не ‎берите‏ ‎трубки ‎с ‎незнакомых ‎номеров. ‎Совсем‏ ‎выключите ‎приём‏ ‎звонков‏ ‎(от ‎незнакомых ‎номеров)‏ ‎на ‎телефоне.‏ ‎Казалось ‎бы, ‎так ‎можно‏ ‎избавиться‏ ‎от ‎кучи‏ ‎лишней ‎информации.‏ ‎Кто ‎обычно ‎звонит ‎с ‎незнакомого‏ ‎номера?‏ ‎Реклама ‎(спам,‏ ‎холодные ‎звонки),‏ ‎а ‎также ‎мошенники ‎и ‎прочие‏ ‎разводилы,‏ ‎которым‏ ‎нужны ‎ваши‏ ‎деньги.

Вот ‎отключил‏ ‎ты ‎звонки,‏ ‎и‏ ‎всё, ‎никто‏ ‎тебя ‎не ‎отвлечёт ‎и ‎не‏ ‎разведёт. ‎Все‏ ‎эти‏ ‎банки, ‎спортивные ‎клубы,‏ ‎мастера ‎ремонта‏ ‎никогда ‎не ‎получат ‎ваших‏ ‎денег.‏ ‎Вы ‎к‏ ‎ним ‎не‏ ‎приходили, ‎а ‎они ‎с ‎вас‏ ‎что-то‏ ‎хотят. ‎Зачем‏ ‎их ‎кормить?‏ ‎Как ‎только ‎мы ‎перестанем ‎отвечать‏ ‎на‏ ‎незнакомые‏ ‎номера, ‎их‏ ‎дело ‎умрёт.‏ ‎Всё ‎ведь‏ ‎так‏ ‎просто, ‎да?‏ ‎Так ‎ведь?

Можно ‎объяснить ‎чисто ‎экономически:‏ ‎раз ‎они‏ ‎звонят‏ ‎тебе, ‎им ‎от‏ ‎тебя ‎что-то‏ ‎нужно. ‎А ‎если ‎им‏ ‎от‏ ‎тебя ‎что-то‏ ‎нужно, ‎насколько‏ ‎это ‎выгодно ‎тебе? ‎Если ‎бы‏ ‎это‏ ‎была ‎win-win‏ ‎ситуация, ‎стали‏ ‎ли ‎бы ‎они ‎тебе ‎звонить?‏ ‎Более‏ ‎того,‏ ‎ни ‎одна‏ ‎win-win ‎сделка‏ ‎на ‎самом‏ ‎деле‏ ‎не ‎является‏ ‎таковой, ‎ведь ‎каждая ‎из ‎сторон‏ ‎идёт ‎на‏ ‎компромисс.

Ну‏ ‎вот ‎и ‎всё,‏ ‎просто ‎отключаем‏ ‎приём ‎звонков, ‎да?

А ‎что‏ ‎если‏ ‎мне ‎нужно‏ ‎принять ‎звонок‏ ‎с ‎незнакомого ‎номера? ‎Я ‎жду‏ ‎курьера,‏ ‎и ‎он‏ ‎мог ‎заблудиться,‏ ‎или ‎у ‎меня ‎перестал ‎работать‏ ‎звонок‏ ‎в‏ ‎дверь. ‎Я‏ ‎жду ‎звонок‏ ‎менеджера ‎(из‏ ‎банка,‏ ‎из ‎того‏ ‎же ‎спортзала, ‎из ‎интернет-магазина, ‎чтобы‏ ‎подтвердить ‎заказ),‏ ‎я‏ ‎не ‎могу ‎не‏ ‎ответить ‎на‏ ‎звонок ‎с ‎незнакомого ‎номера.

Да,‏ ‎курьеры‏ ‎Озон ‎(хоть‏ ‎и ‎не‏ ‎все) ‎уже ‎научились ‎писать ‎СМС‏ ‎и‏ ‎даже ‎в‏ ‎Телеграм, ‎чтобы‏ ‎уточнить ‎время ‎доставки. ‎Но, ‎к‏ ‎сожалению,‏ ‎передать‏ ‎информацию ‎текстом‏ ‎могут ‎не‏ ‎все. ‎И‏ ‎это‏ ‎печально.

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

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Синхронность и асинхронность

Вы ‎обращали‏ ‎внимание, ‎что ‎«синхронный» ‎в ‎реальном‏ ‎мире ‎и‏ ‎«асинхронный»‏ ‎у ‎программистов ‎значат‏ ‎одно ‎и‏ ‎то ‎же? ‎Хотя ‎«а»‏ ‎говорит‏ ‎о ‎противоположности,‏ ‎отрицании.

Например, ‎синхронное‏ ‎плавание ‎было ‎бы ‎в ‎программировании‏ ‎реализовано‏ ‎асинхронно ‎—‏ ‎когда ‎несколько‏ ‎исполнителей ‎выполняют ‎работу ‎одновременно, ‎не‏ ‎мешая‏ ‎друг‏ ‎другу.

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

А ‎есть‏ ‎ещё ‎такие ‎термины, ‎которые‏ ‎противоположны‏ ‎по ‎названию,‏ ‎но ‎бывают‏ ‎равны ‎по ‎значению?

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Люди не поняли ночную тему

Во ‎многих‏ ‎(если ‎не ‎во ‎всех) ‎приложениях‏ ‎есть ‎ночная‏ ‎тема.‏ ‎В ‎большинстве ‎случаев‏ ‎всё ‎белое‏ ‎меняется ‎на ‎черное, ‎а‏ ‎всё‏ ‎черное ‎на‏ ‎белое. ‎Но‏ ‎есть ‎особые ‎случаи, ‎про ‎которые‏ ‎эта‏ ‎заметка.

Есть ‎программы,‏ ‎которые ‎при‏ ‎включении ‎ночной ‎темы ‎становятся ‎СИНИМИ.‏ ‎Синий‏ ‎цвет.‏ ‎Ночная ‎тема.‏ ‎Куча ‎публикаций‏ ‎(и ‎даже‏ ‎выступлений)‏ ‎про ‎то,‏ ‎что ‎синий ‎цвет ‎это ‎лишний‏ ‎раздражитель, ‎и‏ ‎что‏ ‎перед ‎сном ‎(то‏ ‎есть ‎НОЧЬЮ)‏ ‎надо ‎снижать ‎присутствие ‎синего‏ ‎цвета,‏ ‎поэтому ‎у‏ ‎всех ‎производителей‏ ‎давно ‎есть ‎всякие ‎фильтры ‎типа‏ ‎Night‏ ‎Shift ‎(Apple)‏ ‎и ‎Eye‏ ‎comfort ‎shield ‎/ ‎Night ‎Light‏ ‎(Samsung‏ ‎и‏ ‎прочие ‎андроиды),‏ ‎которые ‎делают‏ ‎экран ‎желтым‏ ‎или‏ ‎даже ‎оранжевым‏ ‎(что ‎ночью ‎незаметно, ‎но ‎вот‏ ‎если ‎отключить,‏ ‎то‏ ‎становится ‎больно). ‎И‏ ‎в ‎то‏ ‎же ‎время ‎некоторые ‎сверхразумные‏ ‎менеджеры‏ ‎/ ‎дизайнеры‏ ‎считают, ‎что‏ ‎ночная ‎тема ‎должна ‎быть ‎СИНЕЙ.‏ ‎То‏ ‎есть ‎максимально‏ ‎раздражающей. ‎Не‏ ‎тёмно-серой, ‎не ‎чёрной. ‎А ‎прям‏ ‎синей‏ ‎и‏ ‎голубой. ‎Ну‏ ‎что ‎это‏ ‎такое?

Кстати, ‎на‏ ‎компьютере‏ ‎я ‎перестал‏ ‎пользоваться ‎ночной ‎темой ‎пару ‎лет‏ ‎назад. ‎Оставил‏ ‎только‏ ‎на ‎мобильных ‎устройствах.

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Циклические импорты

Как ‎же‏ ‎легко ‎натолкнуться ‎на ‎циклические ‎импорты.‏ ‎Обычно ‎исправить‏ ‎такую‏ ‎ошибку ‎несложно, ‎а‏ ‎ещё ‎проще‏ ‎не ‎доводить ‎до ‎такого‏ ‎совсем,‏ ‎ведь ‎достаточно‏ ‎следовать ‎нескольким‏ ‎простым ‎правилам:

  • под ‎одну ‎сущность ‎нужно‏ ‎выделять‏ ‎отдельный ‎модуль;
  • для‏ ‎совмещения ‎двух‏ ‎(и ‎более) ‎сущностей ‎создавайте ‎новый‏ ‎модуль,‏ ‎там‏ ‎объявляйте ‎новую‏ ‎обертку ‎(функцию,‏ ‎класс), ‎которая‏ ‎будет‏ ‎выполнять ‎требуемые‏ ‎действия ‎(объединять ‎сущности; ‎делать ‎вызов‏ ‎объектов, ‎и‏ ‎т.‏ ‎д.).

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

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Объективно ли?

Как ‎же‏ ‎странно ‎слышать ‎«объективно ‎это ‎какая-то‏ ‎фигня» ‎или‏ ‎«ну‏ ‎объективно ‎мне ‎это‏ ‎совсем ‎не‏ ‎нравится». ‎А ‎ещё ‎корёжит‏ ‎с‏ ‎«объективно, ‎выглядит‏ ‎красиво!». ‎Что‏ ‎за ‎чушь? ‎Объективно ‎это ‎неоспоримо,‏ ‎непредвзято.‏ ‎Например, ‎ноутбук‏ ‎весит ‎два‏ ‎килограмма ‎и ‎сто ‎грамм. ‎Или‏ ‎что‏ ‎у‏ ‎отдельно ‎взятой‏ ‎машины ‎ровно‏ ‎четыре ‎колеса.‏ ‎Это‏ ‎объективно.

А ‎тяжелый‏ ‎ноутбук ‎или ‎легкий, ‎красивая ‎машина,‏ ‎или ‎страшная,‏ ‎это‏ ‎уже ‎совсем ‎не‏ ‎объективно, ‎это‏ ‎субъективно.

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Програ́ммное обеспе́чение

Програ́ммное ‎обеспе́чение

Програ́ммное‏ ‎обеспе́чение ‎обеспе́чивает ‎рабо́ту ‎компью́тера.

Мы ‎с‏ ‎вами ‎пишем‏ ‎програ́ммное‏ ‎обеспе́чение, ‎и ‎это‏ ‎совсем ‎не‏ ‎обеспече́ние ‎(как ‎некоторые ‎произносят),‏ ‎ни‏ ‎к ‎каким‏ ‎печенькам ‎ПО‏ ‎отношения ‎не ‎имеет ‎(даже ‎если‏ ‎речь‏ ‎про ‎кукисы).

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Этого достаточно

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

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

xfail

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

Так ‎вот, ‎сегодня, ‎ковыряясь ‎в‏ ‎unittest,‏ ‎я ‎для‏ ‎себя ‎открыл‏ ‎декоратор ‎expectedFailure, и ‎у ‎меня ‎появилось‏ ‎понимание‏ ‎значения‏ ‎xfail: ‎«x»‏ ‎читается ‎как‏ ‎«ex», ‎то‏ ‎есть‏ ‎это ‎просто‏ ‎сокращение ‎для ‎«expected ‎failure».

Вот ‎так‏ ‎всё ‎просто,‏ ‎а‏ ‎я ‎и ‎не‏ ‎придавал ‎значения.

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Хватит путать git и GitHub / GitLab

Хватит ‎путать‏ ‎git ‎и ‎GitHub ‎/ ‎GitLab

Что‏ ‎такое ‎git?‏ ‎Система‏ ‎контроля ‎версий. ‎Так‏ ‎почему ‎вы‏ ‎продолжаете ‎писать ‎«git» ‎/‏ ‎«гит»‏ ‎подразумевая ‎GitHub‏ ‎или ‎GitLab?‏ ‎Вы ‎же ‎понимаете, ‎что ‎это‏ ‎разные‏ ‎инструменты? ‎Вы‏ ‎пытаетесь ‎сэкономить‏ ‎три ‎буквы? ‎Почему ‎у ‎вас‏ ‎в‏ ‎голове‏ ‎укладывается ‎фраза‏ ‎«не ‎могу‏ ‎зайти ‎на‏ ‎git»,‏ ‎или ‎«у‏ ‎меня ‎недоступен ‎git»?

Прикиньте, ‎у ‎вас‏ ‎не ‎открывается‏ ‎интернет-магазин‏ ‎в ‎браузере, ‎и‏ ‎вы ‎пишете‏ ‎в ‎поддержку ‎«у ‎меня‏ ‎не‏ ‎работает ‎html».‏ ‎Звучит ‎странно,‏ ‎да? ‎И ‎даже ‎это ‎было‏ ‎бы‏ ‎более ‎логично,‏ ‎чем ‎путать‏ ‎git ‎и ‎сайт ‎по ‎типу‏ ‎GitHub,‏ ‎ведь‏ ‎у ‎вас‏ ‎может ‎быть‏ ‎старый ‎браузер,‏ ‎в‏ ‎котором ‎действительно‏ ‎не ‎работают ‎новые ‎фишки ‎свежего‏ ‎HTML.

Вы ‎бы‏ ‎ещё‏ ‎про ‎Bitbucket ‎писали‏ ‎«git». ‎Или,‏ ‎раз ‎название ‎начинается ‎не‏ ‎на‏ ‎«Git», ‎то‏ ‎не ‎стыкуется?‏ ‎Кстати, ‎а ‎битбакет ‎ещё ‎существует?

Он‏ ‎же‏ ‎Гога, ‎он‏ ‎же ‎Гоша,‏ ‎он ‎же ‎Юрий, ‎он ‎же‏ ‎Гора,‏ ‎он‏ ‎же ‎Жора

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Запускайте код реже

Запускайте ‎код‏ ‎реже

Не ‎нужно ‎запускать ‎код ‎после‏ ‎каждой ‎новой‏ ‎строчки.‏ ‎Не ‎нужно ‎запускать‏ ‎код ‎даже‏ ‎после ‎создания ‎новой ‎функции.‏ ‎Вам‏ ‎кажется, ‎что‏ ‎что-то ‎не‏ ‎так, ‎и ‎что ‎где-то ‎будет‏ ‎ошибка.‏ ‎И, ‎вероятно,‏ ‎это ‎будет‏ ‎так. ‎Особенно ‎на ‎старте. ‎Но‏ ‎не‏ ‎тратьте‏ ‎время ‎зря.‏ ‎Описывайте ‎понятные‏ ‎короткие ‎функции,‏ ‎добавляйте‏ ‎логирование, ‎ловите‏ ‎исключения. ‎И ‎при ‎запуске ‎проверяйте‏ ‎фичу ‎целиком.‏ ‎У‏ ‎вас ‎нет ‎задачи‏ ‎«написать ‎функцию».‏ ‎Есть ‎задача ‎«выполнить ‎работу‏ ‎от‏ ‎А ‎до‏ ‎Б». ‎И‏ ‎вот ‎проверяйте, ‎работает ‎ли ‎фича,‏ ‎а‏ ‎не ‎отдельная‏ ‎функция.

А ‎ещё‏ ‎пишите ‎тесты.

Читать: 1+ мин
С
logo
Сурен Хоренян | Программирование

Полдюжины

Полдюжины

Почему ‎не‏ ‎проще ‎сказать ‎«шесть»?

А ‎на ‎английском‏ ‎вообще ‎«half‏ ‎a‏ ‎dozen» ‎vs ‎«six».

Зачем?

Показать еще

Обновления проекта

Статистика

Метки

Фильтры

Подарить подписку

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

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

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

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

Добавить карту
0/2048