Разница между решением любой проблемы и правильным

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

Как такое возможно?

Питер создал отличную распределенную систему онлайн-бронирования для магазина. Пользователь может выбрать время, доступное для бронирования, в «Экране доступного времени». Мэри, оператор системы, использует код, написанный Питером. Она отвечает за прием следующего человека в очереди и предоставление услуг в магазине.

Однако у системы бронирования есть проблема. Хотя состояние системы обновляется сразу на сервере, пользователь должен обновить страницу или повторно войти на веб-сайт, чтобы увидеть обновления к доступному времени. Таким образом, если два человека одновременно смотрят на экран «Доступное время». они могут создавать одно и то же бронирование одновременно. Если это произойдет в напряженный день, у Мэри возникнут проблемы, пытаясь решить проблему в магазине. Это сделает клиентов недовольными обслуживанием и вызовет разочарование у Мэри.

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

Мэри начинает расстраиваться. Питер тратит слишком много времени, чтобы доставить это.

Через 2 месяца у Питера наступило улучшение. Через несколько дней Мэри замечает, что дублирующихся бронирований больше нет.

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

Питер умен, он все решает не хуже всех!

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

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

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

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

Питер верил, что сможет решить все, но этого не произошло. Разница в том, что он заметил это слишком поздно.

Десять лет спустя я спросил Питера, что он узнал об этом эпизоде ​​с системой бронирования.

Вот что сказал Петр:

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

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

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

Петр привел пример:

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

Как только стоимость переноса станет слишком большой, вы можете автоматизировать процесс.

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

Если затраты на устранение дублирования вручную становятся слишком большими, вы можете создать систему, которая автоматически отправляет пользователю SMS или электронное письмо со словами: «Извините, мы не можем обслужить вас в 10:00, пожалуйста, забронируйте другое время». Вы переключаете значительную стоимость с оператора на небольшое неудобство для пользователя.

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

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

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

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

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

Питер считал себя умным в то время, но ему потребовался многолетний опыт, чтобы понять это ...

… Не умный программист решает все проблемы, а тот, кто понимает, какие проблемы стоит исправить.

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

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

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

Лучше, если не нужно.

Будет лучше, если ты научишься с Питером.

Спасибо за прочтение. Если у вас есть отзывы, напишите мне в Twitter, Facebook или Github.

Благодарим Яна Тинсли и Густаво Хенке за их полезный вклад в этот пост.

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