Основная проблема разработки
Иногда мои знакомые спрашивают: как стать программистом?
Вместо того чтобы просто ответить на вопрос, мне непременно надо придумать что-то максимально основательное, что-то самое важное, с чего надо начать. Например, а что значит быть программистом в современном мире? В чем суть моей работы, так сказать? То что у меня канбан есть и я с понедельника по пятницу тикеты там передвигаю это понятно, но должно же быть какое-то содержание?
В итоге я остановился на мысли, что программирование - это борьба со сложностью
. Вообще, есть большой шанс, что я это вычитал где-то, а не придумал, но я не помню, где, так что буду продавать как свою собственную.
Можно подумать, что когда я говорю сложность, я имею в виду какой-то тяжелый Computer Science, но нет. Есть, конечно, люди, которые отправляют роверы (и иногда даже роадстеры) на марс, но мы-то с вами, простые смертные, в основном штампуем формы и пишем CRUD`ы (или, прости Господи, REST`ы). Еще сейчас стало модно коэффициенты подбирать. Это то, что в огромном количестве требуется современному IT, давайте себе признаемся. Только не надо думать, что я тут эту работу принижаю, она тоже по своему важна, просто мы должны разграничить. Назовем это разработкой общего назначения. Вот именно об этой области и хочется поговорить.
Борьба со сложностью
Сложность, как бы это ни было парадоксально, сама включает в себя много всяких штук. Начиная от взаимоотношений в команде или с заказчиком, через работу с огромным количеством современных инструментов и технологий, и останавливаясь на алгоритмах и структурах данных, что в сумме, как завещал дядька Вирт, и является программой. Все это составляет сложность профессии разработчика. Но есть одна, которую хочется выделить особо, потому что она, мне кажется, причиняет набольший урон.
Эта главная сложность заключается в ограничениях нашего мозга и комбинаторике.
Про мозг все становится понятно, если вы попробуете проследить взглядом выход из трудного лабиринта нарисованного на бумаге. Нет даже не так, попробуйте охватить этот путь целиком и держать его в фокусе своего внимания. Или попробуйте прочитать 30 чисел после запятой числа Пи, а потом повторить их. Да нам даже телефон запомнить трудно, если он не состоит из повторяющихся или последовательных наборов цифр. Собственно цифры человек придумал, потому что ему гораздо проще запомнить "12 палочек", чем запомнить и точно воспроизвести рисунок, на котором было 12 палочек.
На самом деле все это вотчина когнитивной психологии, а я не настоящий психолог. Я просто привел примеры, которые наглядно дают понять, что эволюция не ко всему нас подготовила.
Что касается программ, они не сильно изменились в своей основе за все время существования программирования. Где-то на элементарном уровне это все те же переменные, условия и циклы. Только теперь это миллионы (миллиарды?) переменных, условий и циклов. И мы точно так же не можем охватить единым взглядом весь этот объем. И самая плохая новость в том, что сложность программы растет не линейно.
Это очень просто объяснить на примере игры крестики-нолики. Есть только 2 символа и поле 3 на 3, игроки ходят по очереди. Исходных переменных довольно мало. Есть 9 вариантов первого хода, 9 клеток, куда можно поставить крестик. У следующего игрока остается 8 свободных клеток и количество вариантов его ходов уменьшается. Но, чтобы написать алгоритм игрока в крестики нолики, мне надо просчитать все варианты развития игры и описать свои ответные действия. Мне надо знать все возможные состояния игры. Мы уже выяснили, что есть 9 вариантов первого хода и 8 второго, но вот состояний игры после второго хода 9*8=72. Можно переформулировать это в том смысле, что каждый из ходов рождает свой вариант развития игры. Первый ход реализовал 9 разных вариантов, а второй разбил каждый из этих 9 еще на 8. Полное количество вариантов расстановки символов равно 9*8*7*6*5*4*3*2*1 = 9! = 362880. А мы всего-то начали с поля 3 на 3.
К счастью конкретно в этой игре количество состояний поля будет меньше, потому что некоторые из них сразу ведут к окончанию игры. Понять это свойство и применить его - уже начало борьбы со сложностью. Важно, что все переменные и все ветвления перемножаются друг с другом (не всегда, в худшем случае). Добавление очередной переменной или условия, когда у меня уже достаточно сложная программа, будет не такой простой операцией, как звучит.
Если менеджер проекта просит добавить простой функционал к объемной программе и в ответ слышит чудовищную оценку временных затрат, его удивление, в общем-то, можно понять. Но против сложности не попрешь. Или можно?
Сложность должна где-то обитать
Главный инструмент у человека с древних времен один - голова (не в том смысле, чем он больше всего пользуется, а в том, что дает наибольший профит). Если он не может решить задачу в лоб, он может найти к ней подход. Если у нас нет фотографической памяти, чтобы запомнить рисунок из нескольких десятков вертикальных палочек, мы можем придумать множество абстракций, описывающих закономерности этого рисунка (если они вообще там есть, если нет, то беда).
Я имею ввиду, что от сложности не получится избавится. Некто по имени Fred Hebert написал замечательный пост на эту тему. Отныне сложность постоянный попутчик разработчика, все что мы можем, осознанно ею управлять. (Есть еще вариант сделать вид, что ее нет, но я не советую вам идти этим путем)
Еще одним источником вдохновения для меня стала серия роликов, записанных Ларри Хооном в дополнение к своей книге "Очень эффективный плотник". Эти видео изменили мой взгляд на профессию. Ларри Хоон рассказывает, как он, его брат и еще один помощник за неделю возводят одноэтажный каркасный дом площадью 100 квадратных метров. "Построить такой дом" - Говорит он во вступлении. - "очень не сложно. Но самое главное мы разбили процесс постройки дома на очень простые шаги. Мы работаем эффективно, и мы никогда не жертвуем качеством ради скорости". Что ж, он не сказал самого главного, но все видео наполнены этим - для каждого шага у них есть метод или инструмент, упрощающий этот шаг.
"Мы уверены, что углы этого фундамента прямые и стены ровные", - Говорит Ларри на фоне фундамента дома, заложенного другим подрядчиком. Они занимаются только плотницкими работами! - "Но как плотники мы обязаны это проверить".
Прямой угол проверяется при помощи египетского треугольника, размеры ставятся по заранее заготовленным шаблонам или прямо на месте (чтобы лишний раз не пользоваться рулеткой и не таскать туда сюда кучу досок), все соединения и многие размеры описаны стандартами (и не надо ломать голову над одними и теми же задачами каждый раз), можно использовать мелованную нить, чтобы нанести насечки сразу на много досок за раз. Это лишь малая часть тех приемов, которые использует Ларри, чтобы качественно и без лишней суеты завершить постройку.
Это не призыв становится плотниками. Меня восхищает подход Ларри к своей работе, и мы можем строить свою работу так же: оттачивать мелочи, решать общие, а не частные задачи, думать.
Поработав на некотором количестве проектов, пользуясь продуктами, разработанными другими людьми, наблюдая как выходят обновления, как добавляется функциональность, как выпускаются патчи, призванные быстро закрыть критическую ошибку и как часто разработка намного превышает изначально заложенное время, я понимаю, что сложность чаще побеждает. И ведь написано очень много книжек, как двигаться к такому уровню мастерства, которого Ларри достиг в плотницком деле. Огромное количество разработчиков пишет статьи или выступает, размышляя о различных подходах. Просто по какой-то причине многие проекты и вся эта информация никак не могут встретиться.