company_banner
6 апреля в 11:18

Как в «Додо Пицца» потеряли 8 миллионов за один час из-за технической ошибки, а потом вернули


Историю нашумевшей технической ошибки «Додо Пиццы», партнера Яндекс.Кассы, нам рассказал системный архитектор компании Андрей Моревский — сразу передаю микрофон автору.


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


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


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


Немного ретроспективы и информации о потерях.

Наш сервер отменил платежей на 7,84 миллиона рублей. Для сети с ежегодным оборотом почти в 3 миллиарда это серьезные деньги. К тому же, это более 10% от привлеченных за последний раунд инвестиций. Согласитесь, слишком серьезная цена для одной ошибки.


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


И сразу спойлер — все закончилось хорошо


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


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


Деньги нам в итоге вернули, хотя мы и потеряли на банковских комиссиях 150 тысяч рублей за переводы, еще 40 тысяч ушло на SMS-уведомления клиентов..


В поисках причин и следствий


С первого дня «Додо Пицца» разрабатывает собственную информационную систему (Dodo IS).

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


Мы тестируем Dodo IS на нескольких окружениях: есть «песочницы» для демонстрации продуктовым менеджерам, есть интеграционные контуры. Перед выкладкой в продакшн финальная версия тестируется аналитиками и QA в окружении stable. Для проверки мы используем реальные данные, которые регулярно копируем с «боевой» базы. Разумеется, все данные при пересечении границы продакшн-**среды** обезличиваются.


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


За день до инцидента произошло сразу два неудачных совпадения, в лучших традициях законов Мерфи:


  • из-за ошибки в конфигурации оказалось, что фоновая задача смотрит не на имитацию платежного сервиса, а на реальное подключение к Яндекс.Кассе;


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

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


Про виновных, ответственность и доверие


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


«Безусловно, мы сделаем серьезнейшие выводы из этой критической ошибки. Мы не будем наказывать людей — мы просто сделаем все, чтобы такого больше не повторилось.»
Сообщение на странице Федора Овчинникова в Facebook и ВКонтакте сразу после инцидента.

Страх наказания рано или поздно парализует работу любой компании. Уверен, многим из вас встречались компании, где пишут много документов и писем, чтобы оказаться как можно дальше от «области поражения». Где ни один менеджер не готов принять ни то что смелое, но даже пустяковое решение без 20-ти согласований. Я считаю, что такие компании не способны к созиданию и развитию, им остается лишь годами «доедать» ресурсы, созданные их более смелыми предшественниками-первопроходцами.


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


«Если есть вероятность того, что какая-нибудь неприятность может случиться, то она обязательно произойдёт.»
Закон Мерфи.

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


Теперь самое интересное — что делать


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


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


Последние полгода мы занимаемся реинжинирингом системы и переводим наш монолит на рельсы SOA (Service-Oriented Architecture). Сегодня каждый в компании — от программистов до управленцев — понимает, что технический долг необходимо возвращать.


В рамках перевода системы на SOA мы выделяем отдельный сервис обработки платежей — платежный шлюз. Этот сервис инкапсулирует всю платежную логику, включая взаимодействия с эквайерами. Фактически, мы разрабатываем собственный платежный агрегатор для собственных нужд. Платежный шлюз станет единой точкой проведения онлайн-платежей для клиентского сайта (dodopizza.ru) и других наших интернет-каналов продаж.


Мы решили сертифицировать платежный шлюз по PCI DSS Self-Assessment. Идея может выглядеть спорной (ведь карточные номера PAN мы не храним), но стандарт PCI DSS — это не бюрократическая формальность, а чек-лист, состоящий из правильных практик и советов по работе с sensitive-данными и написанный «кровью».


Платежный шлюз изнутри


У каждого платежного шлюза должна быть архитектура, описанная UML-диаграммой. Так выглядит компонентная модель нашего шлюза:


image alt text


А вот что находится внутри IBackService, IPlugin и прочих интерфейсов:


image alt text


Но сколько диаграмм не рисуй, а словами объяснять все равно придется :) Из чего же состоит шлюз, и какую роль выполняют его компоненты?


Клиентский сайт


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


Платежный шлюз


Шлюз представляет собой RESTful-сервис, который принимает запросы на возвраты и оплату заказов, для чего предоставляет два API:


  1. Back API предназначен только для вызовов со стороны Dodo IS и доступен только в DMZ.


  2. Public API открыт всему интернету — он обрабатывает запросы эквайеров и перенаправления пользователей с клиентского сайта.

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


Плагины


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


Сервисы данных и база данных


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


Чтобы нагляднее увидеть роль каждого компонента и представить, куда и как текут данные, предлагаю посмотреть на диаграмму потоков данных:


image alt text


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


Типовой сценарий проведения платежа в новой архитектуре на примере Яндекс.Кассы.

Сценарий начала оплаты


N Шаг Пример (Яндекс.Касса)
1 Клиент находится на Клиентском сайте и переходит к оплате заказа. -
2 Клиентский сайт запрашивает у Платежного шлюза доступные для конкретной пиццерии безналичные способы оплаты, вызывая метод GetPaymentTypes. -
3 Клиентский сайт отображает клиенту способы оплаты. Клиент выбирает способ оплаты. Клиент выбирает оплату через Яндекс.Кассу
4 Клиентский сайт отправляет запрос на создание платежа в Платежный шлюз, вызывая метод CreatePayment. Передаются выбранный способ оплаты, идентификатор пиццерии, идентификатор заказа, сумма к оплате, URL'ы оповещения о статусе платежа, успешного возврата и неуспешного возврата. -
5 Платежный шлюз создает платеж в статусе Draft. -
6 Платежный шлюз валидирует платеж и присваивает ему статус Accepted или Rejected. -
7 Платежный шлюз возвращает платеж Клиентскому сайту. -
8 Если платеж отклонен (Rejected), то Клиентский сайт показывает клиенту ошибки и сценарий заканчивается. -
9 Клиентский сайт определяет тип встраивания Платежного шлюза. Тип встраивания указан для каждого способа оплаты.
если тип встраивания «через редирект», Клиентский сайт перенаправляет клиента на страницу оплаты Платежного шлюза PaymentPage, передавая идентификатор платежа.
если тип встраивания «через фрейм», Клиентский сайт отображает клиенту фрейм, в котором открывает страницу оплаты Платежного шлюза PaymentPage, передавая идентификатор платежа.
Тип встраивания для Яндекс.Кассы — «через редирект». Поэтому Клиентский сайт перенаправляет клиента на страницу оплаты Платежного шлюза PaymentPage, передавая идентификатор платежа.
10 Платежный шлюз присваивает платежу статус Started, если платеж находится в статусе Accepted. В противном случае, переходим к сценарию неуспешного завершения оплаты. -
11 Платежный шлюз отображает страницу оплаты с анимацией ожидания. -
12 Платежный шлюз валидирует платеж по идентификатору. Если валидация не пройдена, переходим к сценарию неуспешного завершения оплаты. -
13 Платежный шлюз по способу оплаты определяет плагин, который будет проводить платеж через эквайера. Если плагин не найден, переходим к сценарию неуспешного завершения оплаты. Выбирается плагин для Яндекс.Кассы.
14 Платежный шлюз вызывает у плагина метод StartPayment, передавая платеж. -
15 Плагин выполняет свои специфичные действия, вызывает системы эквайера и возвращает шлюзу результат. Плагин возвращает Платежному шлюзу результат «редирект» и URL страницы оплаты в Яндекс.Кассе
16 Платежный шлюз обрабатывает результат плагина:
если результат — «ошибка», Платежный шлюз переходит к сценарию неуспешного завершения оплаты.
если результат — «платеж проведен», Платежный шлюз возвращает ответ, полученный из плагина, и переходит к сценарию успешного завершения оплаты.
если результат — «ожидание», Платежный шлюз возвращает ответ, полученный из плагина.
если результат — «редирект», Платежный шлюз осуществляет перенаправление на URL, полученный из плагина, и переходит к сценарию ожидания оплаты.
Платежный шлюз перенаправляет клиента на URL страницы оплаты в Яндекс.Кассе и переходит к сценарию ожидания оплаты.

Сценария ожидания оплаты


N Шаг Пример (Яндекс.Касса)
1 Платежный шлюз прослушивает запросы эквайера через универсальный endpoint Acquiring. Этот же endpoint обрабатывает и редиректы клиента, инициированные эквайером. Яндекс.Касса отправляет HTTPS POST на адрес pay.dodopizza.com/acquiring/yamoney/checkOrder
или
Яндекс.Касса отправляет HTTPS POST на адрес pay.dodopizza.com/acquiring/yamoney/checkAviso
или
Яндекс.Касса перенаправляет клиента на адрес pay.dodopizza.com/acquiring/yamoney/success
2 Получив запрос, Платежный шлюз извлекает из параметров запроса имя плагина и создает соответствующий плагин Платежный шлюз по имени yamoney находит плагин для Яндекс.Кассы
3 Платежный шлюз авторизует запрос, вызвав метод плагина AuthorizeAcquiringRequest Плагин проверяет подлинность запроса.
4 Платежный шлюз отправляет запрос на обработку плагина, вызвав метод ProcessAcquiringRequest. Плагин выполняет свои специфичные действия и возвращает шлюзу результат. По параметрам запроса плагин выбирает соответствующий обработчик.
CheckOrder:
Плагин возвращает шлюзу результат «ожидание» и ответ для отправки Яндекс.Кассе
CheckAviso:
Плагин возвращает шлюзу результат «платеж проведен» и ответ для отправки Яндекс.Кассе
success:
Плагин возвращает шлюзу результат «редирект» и URL успешного возврата.
5 Платежный шлюз обрабатывает результат плагина:
если результат «ошибка», Платежный шлюз переходит к сценарию неуспешного завершения оплаты.
если результат «платеж проведен», Платежный шлюз возвращает ответ, полученный из плагина, и переходит к сценарию успешного завершения оплаты.
если результат «ожидание», Платежный шлюз возвращает ответ, полученный из плагина.
если результат «редирект», Платежный шлюз осуществляет перенаправление на URL, полученный из плагина, и переходит к сценарию ожидания оплаты.

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

Автор: @dimskiy
Яндекс.Деньги
рейтинг 162,25
Об электронных платежах и устройстве Я.Денег

Комментарии (71)

  • 0
    я правильно понял, тестовые заказы на 7,84 миллиона рублей?
    • +3
      судя по статье, это были реальные платежные операции из копии продакшен-базы, которые в результате «обезличивания», (а вернее чистки части данных с продакшена), потеряли связь с заказами. А поскольку транзакции и реляционная целостность в современном мире считается устаревшим подходом, для приведения базы в порядок был специальный сервис, отменяющий платежные операции, не привязанные к заказам. Интересно, почему на продакшене нельзя было делать этого вручную, или может даже исправить причину появления таких операций?
      • 0
        судя по статье это были не реальные платежи
        Особенно обидно было осознавать, что мы вернули деньги, которых не получали — это были тестовые заказы.
        • 0
          Вернуть деньги можно только тому, кто их перечислил. И судя по плате за SMS уведомления это были вполне реальные люди
        • +3
          Под «тестовыми заказами» имеются ввиду реальные заказы на тестовой базе. Наверное, неудачная формулировка получилась.
    • +2
      Это были реальные заказы, загруженные с продакшн-базы в тестовую базу.
      • +3
        Знакомьтесь — это Андрей, представитель Додо Пицца.
        • +4
          Да, я тот самый Андрей Моревский, который автор статьи :)
  • +2
    > На stable-окружении мы стараемся полностью воспроизводить боевые условия — в том числе отмену не привязанных к заказам платежей. В реальных условиях такие платежи могут иметь место из-за ошибок в процессе оплаты или из-за некорректно отработавшей процедуры отмены заказа пользователем.

    Вот этот момент вызывает много вопросов и удивляет меня. Как это может быть так, что платеж есть, а заказа нет? Это пополнение баланса в системе? Если нет — то какое основание есть для формирования счета на оплату и проведения платежа? Вряд ли вам пользователи просто так денег засылают. Поясните пожалуйста, если не сложно.

    P.S. Яндекс.Кассу подключал, как она работает в курсе.
    • 0
      За время проведения оплаты пиццерия может встать в стоп (надо почистить печь, выключилось электричество, другие экстренные ситуации). В этом случае оформление заказа не происходит и такие платежи возвращаются автоматически по расписанию.

      • +2
        А что в вашем понимании тогда оформление заказа? То есть вот я выбрал пиццу, сделал заказ, оплатил, это ещё не оформление? То есть я могу заплатить за товар, который «вы» не можете продать?
        • +1
          После оплаты мы делаем финальную проверку заказа и уже после проставляем статус, что заказ отправлен на исполнение.
          • +1
            Окей, я понимаю, но как оплата может быть не привязана к заказу в ситуации НЕошибки во время платежа? То есть оплата платежа происходит ведь именно по айдишнику.
            • 0
              Там алгоритм смотрит, что должен быть заказ в определенной стадии. Если заказа нет, то платеж считается непривязанным и должен быть возвращен.
              • 0
                ХитрО!
              • +1
                Это возвращение к исходному вопросу. Как может быть оплата без заказа? Заказ это поручение исполнителю выполнить определенную работу (привезти пиццу). Вряд ли кто-то платит, ничего не заказывая. Если бы платежи и возвраты были привязаны к заказам, проблема вообще не возникла бы. Т.к. у вас пошли возвраты по уже оплаченным и даже возможно доставленным заказам.

                Что конечно же совершенно недопустимо с точки зрения архитектуры и бизнес-процессов. Или я неверно понял ситуацию? Ведь фактически вы отправляли деньги за оплаченные и/или доставленные заказы. Чего, по идее, не должно было происходить. Хоть на тестовой базе, хоть где. Сама попытка такое провернуть должна выбрасывать критическое исключение.
                • 0
                  Заказ как сущность в БД существует на момент оплаты и даже раньше. Дело не в этом. Дело в том, что после оплаты мы перепроверяем, не стала ли пиццерия в стоп за то время, пока клиент оплачивал (или не случилось ли что-то другое, что не даст исполнить заказ). И если исполнение заказа невозможно, мы говорим об этом клиенту и возвращаем деньги. За возврат денег отвечает фоновая задача, которая работает так: она ищет платежи, к которым не привязаны исполненные заказы, и отменяет эти платежи.
                  • 0
                    Спасибо что поясняете. Я пытаюсь понять логику возникновения проблемы. Что-то как ни тужился, не понял ее из статьи. Скрипт нашел заказы оплаченные, но не исполненные. И вернул за неисполненные но оплаченные заказы деньги. Это вроде так и должно у вас работать в обычном порядке? Или данная операция была проведена повторно?
                    • 0

                      Заказы в продакшен-базе были оплачены и выполнены. При копировании в тестовую базу обезличивание данных сделало какие-то заказы невыполненными. Скрипт откатил оплаты по этим заказам. Но откатил не по тестовому шлюзу, а по живой Яндекс.Кассе :)

                      • 0
                        Да, именно так
                        • 0
                          Спасибо, теперь понятно. Экзотическое у вас однако обезличивание для стенда, которое фактически меняет статус заказов.
                    • 0
                      Посмотрите ниже ответ Chupaka, там все верно описано.
                  • +1
                    Насколько я понял, тут просто была не очень хорошо продумана логика.
                    Из того, что я прочитал, мне представляется, что в норме бесхозные оплаты всё равно не должны возикать — вы же не удаляете заказы сразу после того, как их застопорили?
                    Соответственно, автоматом отменять нужно только те оплаты, которые привязаны к застопоренному заказу.
                    А возникновение вообще бесхозной оплаты должно считаться нештатной ситуацией. И если такое обнаруживается, то нужно отправлять аларм человеку, который будет руками разбираться, почему случился такой пердимонокль.
                    • 0
                      Согласен с вами
        • 0

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

          • 0
            Хм, ну насколько я понимаю в данном случае деньги не блокировались, а сразу уходили. Иначе бы, всем клиентам тупо вернулись их кровные. А во-вторых, даже если деньги блокируются и транзакций 2, то в первом случае уже есть привязка к некоему id, ну вот не понимаю я как можно получить деньги не привязав их сразу к какому-то родительскому id, пофиг на то, что то там дальше бужет, success_transaction_id, success_order или fail, какой-то parent_id у них обязан быть!
            • 0
              1. да, скорее всего так.
              2. при первой транзакции создается ее id, который в дальнейшем и финишируется, если все устраивает получателя, либо финишируется с корректировкой суммы

              P.S.: Мы работали по DMS с эквайером, чтобы избежать эксцессов по поводу отсутствия товара и оплаченной сумме. После перехода к Я.Кассе нам пришлось запретить оплату несобранных заказов в личном кабинете пользователей. И это очень неудобно добросовестным клиентам

  • –22
    Как бы не удивительно что такие проблемы ведь чудо написано на C#.
    • +4
      Видимо я что-то страшное не знаю про С#.
    • +1
      А что не так с C#?
    • +5

      На asm бы такого не случилось, ибо они бы до сих пор писали первый сервис.

  • +2
    Обеспечивая бурный рост Dodo IS, мы нередко предпочитали скорость разработки всему остальному. Иногда это происходило в ущерб системной логике, архитектуре и инфраструктуре.

    У меня приятель в Dodo работал. Рассказывал, что подобные «ускорения» приводили к тому, что js и css писали прямо в cshtml файлах в массовом порядке. Описанная в статье проблема была конечно архитектурная, а не тактическая, но симптомы на лицо. Он ушел из Dodo, потому что боялся что «ускорения» к чему-то подобному приведут. Надеюсь выводы сделаны и в дальнейшем у Dodo будет рост качества кода и безотказности системы! А пицца и так вкусная)
    • +1
      Там программистов тоже заставляют на кухне поработать для начала? А то у Федора в блоге (который был весьма интересным когда он писал про макдак и пападжонса) весьма в категоричной форме заявлено что все обязаны работать на кухне при поступлении.
      • +5
        Кстати, это классный опыт — побывать на всех этапах цепочки, чтобы понимать какую боль ты порой доставляешь персоналу кажущимися гениальными техническими решениями :) Эх, вот бы безопасники хоть иногда работали на месте тех, кому закручивают гайки
        • 0
          Это конечно безусловно так, но это доведение до абсурда. Я так понимаю, если бы это была клининговая компания, программистов информационной системы бы там заставляли полы мыть, чтобы поняли почем фунт лиха.
          • +1
            Если эта информационная система автоматизирует сам процесс клининга, то — да, и программистам и архитекторам и другим инженерам будет полезно помыть пол, используя свою же систему. А если система автоматизирует прием заказов на клининг, то мыть пол не нужно, а будет полезно поработать оператором.
            Это называется https://en.wikipedia.org/wiki/Eating_your_own_dog_food, и продукт в результате получается в сто раз круче.
            • 0
              Вы кажется путаете роль дизайнера/юзабилитиста (простите, не знаю как по русски)/аналитика и
              инженера.

              Для того чтобы писать хороший отказоустойчивый бакенд или разрабатывать архитектуру платежного гейта, или быть хорошим DBA или админом линукс-сервера не нужно знать специфику приготовления теста.
              Возможно для тех кто делает фронтенд — да, полезно. Для тех кто делает скетчи интерфейса. Для менеджеров (и то, для тимлидов именно разработки — под вопросом). Но заставлять это делать ВСЕХ разработчиков и инженеров — это просто блажь и упоротость Федора.

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

              Ну и Eating your own dog food это немного про другое. Это когда компания пользуется своим продуктом постоянно, а не когда нет разделения между программистами и уборщицей.
              • 0
                Простите, но вы немного перегибаете.

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

                «И поработать официантом, потому что они через сколько-то слоев взаимодействуют с бакендом»
                В пиццерии нет официантов.

                «И поработать уборщицей в туалете, потому что у вас вот все сотрудники взаимозаменяемы.»
                Мы не автоматизируем уборку туалетов, так что это лишнее

                «Для того чтобы писать хороший отказоустойчивый бакенд или разрабатывать архитектуру платежного гейта, или быть хорошим DBA или админом линукс-сервера не нужно знать специфику приготовления теста.»
                Знать специфику приготовления теста не обязательно. Понимать, как работает пиццерия изнутри обязательно. От этого однозначно не будет хуже — как минимум, это новые знания, расширение кругозора и т.д. В нашем же случае мы видим очевидную пользу от этого — такие стажировки влияют на мотивацию людей и на отношение к разрабатываемому продукту.
                • +1
                  У нас пока нет аппов для курьеров. Но где-то через год они будут и тогда — да, поработать курьером будет полезно

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

                  В пиццерии нет официантов.

                  Ну и что? Это ваша модель бизнеса, я же в целом говорю… Если бы официанты были, я так понимаю разработчики бы работали ими в том числе?

                  как работает пиццерия изнутри обязательно

                  Для этого совершенно необязательно работать неделю в Сывтывкаре.

                  От этого однозначно не будет хуже

                  Не будет. Но будет ли лучше — далеко не факт. Возможно это время стоило бы потратить на изучение чего-то более полезного. Например как логику тестирования платежей делать.
                  • +3
                    «Потому что работа курьером — это мягко говоря низкоквалифицированный, тяжелый и достаточно небезопасный труд.»
                    Можно просто доставить несколько заказов, находясь рядом с настоящим курьером. Было бы желание, а решение найдется.

                    «Для этого совершенно необязательно работать неделю в Сывтывкаре.»
                    Необязательно в Сыктывкаре и неделю. Пиццерии есть в Москве.

                    «Но будет ли лучше — далеко не факт.»
                    Наш опыт показывает, что будет лучше. Опыт — штука субъективная, я понимаю. Что и хочу донести в нашей переписке.
        • +1
          Не знаю как при поступлении на работу, но очень интересным «наказанием» в случае серьезного косяка я считаю предложить разработчику посидеть на саппорте клиентов.
      • 0
        Заставляют — не совсем верное слово. Это условие работы, которое обговаривается заранее. Можно проходить стажировку не с начала, а через полгода, например.
        • +1
          Я более чем уверен, что это условие срезает большую часть квалифицированных людей.
          • +3
            Квалификация нарабатывается. Мосигра как-то писала, что иногда набирает в ИТ продажников с некоторыми зачаточными ИТ-навыками, а потом доучивает. С позиции рядового сотрудника это неочевидно, но учить легче, чем перевоспитывать.
            • +1
              Именно так.
            • 0
              Она набирает эникейщиков, хелпдеск на местах. Архитектора и даже сеньор девелопера вы из пиццайоло с зачаточными навыками айти за вменяемое время не подготовите.
              • +1
                Нет там хелпдеска на местах.
                За вменяемое время кого угодно можно подготовить. Не знаю ни одного специалиста ни в одной области, который учился бы невменяемое время.
                • +1
                  Разработчика уровня сеньора не говоря уже про архитектора вы не подготовите из человека с зачаточными IT-навыками менее чем за 5-10 лет. Это даже не учитывая что хороший разработчик на одном таком проекте как ИС додо-пицца не вырастет.
    • 0
      Не очень-то и вкусная. 6/10
      • –2
        Совсем невкусная. Из массовых лучшая у Папа Джонса, не в каждой пиццерии получается хрустящая рельефная корочка, но даже без неё пицца далеко впереди конкурентов из Пиццы Хат (совсем не как в 90-е) и Доминос (у них беда с рецептами).
        А Додо может конкурировать с Империей пиццы и прочим локальным продуктом.
    • +1
      > Он ушел из Dodo, потому что боялся
      Зря боялся:
      > Мы не будем наказывать людей

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

      Итог: Вместо того, чтобы попробовать направить в нужное русло он просто свалил…
  • +1
    Я так и знал: навыки, аккуратность и опыт не заменишь UML-диаграммами.
  • 0
    Советую в архитектуру добавить систему антифрода — без нее вы в будущем получите еще много неприятностей.
    И да, ни какой финансовый запрос в АПИ не должен выполняться в обход системы антифрода. Это аксиома для платежного шлюза. У разработчика не должно быть шансов создать endpoint в АПИ не унаследовав базовые проверки в антифроде. В первом приближении система антифрода может быть обычной таблицей барьерных лимитов.
    • 0
      Можно для не-специалистов указать, что доброго почитать по теме?
    • 0
      Спасибо! Да, планируем антифрод после запуска первой версии шлюза.
  • –2
    А меня за такие косяки по рукам били. И я бил.

    Неужели Senior Developer не поменяли? Просто пройтись по статье — косяков Senior Developer немеряно, начиная от «сильной связи». Жесткие такие косяки.

    Хотя, такие люди, как правило, очень амбициозны, и поэтому очень убедительны. "Я создал монстра, и потратил на это много денег" — и его начальство любит и очень ценит, ведь он так крут. «Unix Way? Игрушка. Устойчивая распределенная архитектура? Оставьте это для учебников...»

    Только в любой другой действительно ИТ-ориентированной компании такой надолго не задержался бы.

    Простите за прямоту.
    • +1
      Вообще, вы правы. Но реальность бывает разная. В данном конкретном случае скорее всего бизнесу было важно как можно раньше получить готовый продукт и стоимость его последующего переделывания вполне могла оказаться (как реально, так и по предварительным расчетам) ниже чем стоимость выпуска системы с нормальной архитектурой, но позже. И действительно хороший сеньор должен понимать такие вещи и быть способен написать (вместе с командой конечно я не имею ввиду в одиночку) плохо, но максимально быстро. А если систему после этого еще и в принципе возможно переделать хорошо и правильно без ее остановок — то это практически идеальный вариант.
      • 0
        Схемку на коленке можно накидать за 5 минут.

        5 минут как-то задержат интеграцию? Спорим, они на тысячу порядков больше времени потеряли?
    • 0
      Бить надо тогда, когда точно известны требования, и их не учли.
      А когда вы растете на 100% в год, и так несколько лет подряд. Вот тогда, чтобы ты не напридумывал сегодня через некоторое время это станет неактуальном в любом случае. Либо бизнес загнется, либо надо все переделывать под новые требования. Если делать хорошо, но долго, бизнес может к тому времени загнуться.
    • 0
      Обеспечивая бурный рост Dodo IS, мы нередко предпочитали скорость разработки всему остальному. Иногда это происходило в ущерб системной логике, архитектуре и инфраструктуре.

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

  • +1
    Очень радует тенденция публикования историй факапов, в которых:
    «Безусловно, мы сделаем серьезнейшие выводы из этой критической ошибки. Мы не будем наказывать людей — мы просто сделаем все, чтобы такого больше не повторилось.»

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


    И изменение, видимо, разработчик делает на выделенной машине без доступа в интернет с выдранными внешними портами и перенакатом образа ОС каждые два часа, под неусыпным присмотром охранника.

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

    Привет, Андрей, весело у тебя там.
  • –1
    Как-то такие статьи очеловечивают компанию. Не было мысли попробовать заказать у вас, а сейчас сижу ем
  • –2
    Всем привет.
    Ситуация с Додо-пиццей привлекла и моё внимание. Именно из-за того, что
    Примерно полтора года назад мы в CloudPayments сделали возможность отменять совершенные возвраты в течение 3 часов после их совершения: в это время мы еще не отправляем окончательное подтверждение в МПС. Кроме того, даже если эти три часа будут упущены, не получится сделать возвратов больше, чем на суточный оборот.
    И в этой ситуации, чтобы не отменять вручную возвраты по всем этим 10000 заказов, можно было бы написать или позвонить в нашу поддержку, мы бы эти возвраты завернули в течение пяти минут.
  • 0
    недавно в развлекательных сетях проскакивала новость, что в до-до пицца сейчас вся внутренняя переписка только на английском, это правда?
    • 0

      Так вот в чем дело )))

  • 0
    Классика. Рано или поздно многие это проходят. Мы в свою очередь «привязали» продакшн условно к серверу — любое перемещение в тестовую среду просто отключает реальные клиентские сервисы…
    • 0
      А как у вас ПО узнает, что оно в тестовой среде?
      • 0
        Я думаю решений много и они очень индивидуальны в каждой системе. Если очень просто и условно, то у сервиса существует настройка — продакшн сервер. Запускаясь в тестовой среде сервис понимает, что его запустили не там где надо, и исходя из этого надо использовать альтернативную конфигурацию или что-то отключить. Параметр настройки я привел здесь достаточно условно — это может быть любым (любыми) отличиями тестовой среды.
  • +1
    Не понимаю, как Вы еще не разорились. Никакой информации про цену доставки, про режим работы. Сидел в 3 часа ночи выбирал пиццу, регистрировался, вбивал код с телефона — и это все чтобы узнать что никто ночью не может принять мой заказ? Я удручен таким обслуживанием.
  • 0
    Сейчас опять пытался заказать ту же пиццу, третий раз ввожу адрес, и этого недостаточно, надо нажать «оформить», чтобы узнать, что теста для кругов среднего размера нет в наличии, зато есть побольше и подороже. В пиццерии тесто закончилось? — Офигеть, это как-то больше похоже на разводилово.

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

Самое читаемое Разработка