Я утверждаю, что большинство инженеров-программистов (особенно тех, кто работает над инфраструктурными проектами) обречены погрязнуть в ненужной сложности из-за трех фундаментальных законов.
Первый закон сложности программного обеспечения.
Хорошо спроектированная система со временем превращается в плохо спроектированную
Начнем с определения, которое мы считаем ошибочным: хорошо спроектированная система — это та, которую легко изменить со временем; плохо спроектированная система — это та, которую трудно изменить. Допустим, система X хорошо спроектирована. Кто-то приходит и меняет ее — по определению, быстро и легко — на другую систему X’.
Теперь X’ либо продолжает быть хорошо спроектированной; в этом случае ее можно быстро и легко снова изменить на другую систему X»; либо она переходит в плохо спроектированное состояние и, следовательно, ее трудно изменить.
Например, рассмотрим хорошо спроектированную базу данных, которая использует RocksDB для реализации чистого API хранения. И кто-то приходит и добавляет в нее вызов getLevelSize; теперь базу данных уже нельзя легко модифицировать для работы с не-LSM движком хранения. Из этого следует, что хорошо спроектированная система — это нестабильное, эфемерное состояние, а плохо спроектированная — стабильное, постоянное состояние.
Соответственно, смесь систем в природе постоянно деградирует в сторону плохого дизайна. Вторая производная кода в нормальных условиях всегда отрицательна: скорость изменения кода со временем снижается. Исходя из этого закона, большинство инженеров будут работать над системами с плохим дизайном, потому что большинство систем со временем превращаются в системы с плохим дизайном.
Второй закон сложности программного обеспечения.
Сложность — это ров (заполненный негерметичными абстракциями)
Проектирование хорошей абстракции — это изящный танец между обеспечением полезности для приложения и сокрытием деталей реализации. Когда системы конкурируют друг с другом за долю рынка, деликатность отходит на второй план, и разработчики часто предоставляют приложению все, что оно хочет. Это дает двойной эффект: увеличивает долю рынка, привлекая разработчиков приложений, и одновременно затрудняет замену под капотом на конкурирующие системы. Некоторые из самых успешных систем на планете имеют API, которые практически невозможно реализовать каким-либо другим способом (на ум приходят более сильная, чем линеаризуемая, согласованность ZooKeeper и семантика эфемерных узлов на базе TCP/IP, а также семантика идемпотентных продюсеров Kafka). Исходя из этого закона, большинство инженеров будут работать над плохо спроектированными системами, потому что большинство успешных/популярных систем — это плохо спроектированные системы.
Третий закон сложности программного обеспечения.
Не существует фундаментального верхнего предела сложности программного обеспечения
В реальных системах, которые создаются большими группами людей в течение долгого времени, сложность ограничивается только творческим потенциалом человека. Форма системы определяется способностями, философией и идиосинкразией десятков разработчиков, каждый из которых работает в рамках сложного набора реальных и предполагаемых стимулов.
Например, почему эта репликационная база данных использует собственный Gossip слой для обнаружения сбоев, а не полагается на Kubernetes? Возможно, тимлид Алиса и разработчик Боб согласились, что обнаружение сбоев в Gossip слое — это то, что нужно. Но как только Боб написал код, Алиса поняла, что это неправильный подход в контейнерной среде. А Чарли, менеджер, уже написал промо-документацию для Боба, и Алиса не хотела брать на себя политический риск блокировки PR. А может быть, система была изначально разработана Бобом для неконтейнерной среды, где Gossip действительно были хорошим выбором. Или, может быть, докторская диссертация Боба была посвящена протоколам, основанным на “эпидемическом протоколе”. Возможно, Алиса затем разделила членство и выборы лидера на разные уровни, чтобы не враждовать с Бобом и Чарли, поэтому в вашей системе теперь есть два слоя с интересными взаимодействиями. Каждая существующая система — это DoS-атака на вас от десятков людей, которых вы, возможно, даже не знаете; заминированный дворец с тикающими бомбами замедленного действия, заложенными на годы раньше вашего участия. Исходя из этого закона, инженеры, работающие с плохо спроектированными системами, будут особенно страдать, поскольку плохо спроектированные системы имеют неограниченную сложность.
Что мы можем сделать с таким положением дел? В своей карьере я придерживался особого подхода, основанного на создании новых систем с нуля (пока они не поддались действию трех законов), но это гораздо сложнее, чем кажется — подробнее об этом в другой статье.