Keep it simple, stupid

30 August 2010 simplicity

Простота. Краеугольный камень нашей профессии. Наверняка вам приходилось слышать от своих коллег: “это можно сделать гораздо проще”. Или вы говорили это вашим коллегам: “смотри, можно сделать так. Это ведь гораздо проще”, а в ответ получали взгляд полный непонимания, как бы говорящий вам: “и это ты считаешь проще?”.

В программной инженерии определенно произошла инфляция слова “простота”.

Find X

Простота – это расстояние

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

Что мы считаем простым? Процессы и объекты чье поведение легко предсказать. Если “оно” ведет себя так как я от “него” ожидаю, значит я понимаю как “оно” работает и скорее всего смогу “его” изменить не поломав. В противоположность этому, если “оно” ведет себя непредсказуемо, значит я не понимаю основополагающих принципов лежащих в “его” основе. И любая попытка “его” изменить может окончится таким же непредсказуемым результатом. В этом случае процесс постулируется слишком сложным.

Такие “предсказания” возможны благодаря тому что в голове человека есть ментальная (поведенческая) модель описывающая этот процесс или объект. И чем сильнее соответствует модель реальности, тем проще расценивается объект. Так что да, простота есть расстояние. Расстояние между ожидаемым и действительным.

Мера простоты – понятие субъективное

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

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

Но более интересна обратная ситуация. Если вы считаете какой-то процесс сложным, это еще не означает что процесс объективно непредсказуем и непонятен. Это может означать что у вас просто нет подходящей поведенческой модели. Возможно не стоит клеймить все вокруг сложным, возможно просто стоит… научится?

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

def qsort: List[Int] => List[Int] = {
  case Nil => Nil
  case pivot :: tail =>
    val(lessThan, greaterOrEqualThan) = tail partition(_ < pivot)
    qsort(lessThan) ::: pivot :: qsort(greaterOrEqualThan)
}

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

​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​Помните этот комикс? ​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

Your Product

Последний продукт просто ужасен, верно? Или нет? Я незнаю. Мне ясна посылка этого комикса, — существует тенденция к чрезмерному усложнению вещей (или их недостаточному упрощению, как вам больше нравится).

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

Ту-154М

Это кабина еще советского Ту-154М, реактивного самолета выпуска середины 80-х. Обычный человек не сможет идентифицировать большинство приборов, рычагов управления и их назначения. Значит ли это что интерфейс сложен для тех для кого он создавался, для пилотов?

Тенденции к упрощению существуют и в авиации, так что мы можем поискать более простой реактивный лайнер (так сказать, “для нубов”). Давайте посмотрим на кокпит широкофюзеляжного A380, который начал эксплуатироваться в 2007 году. Считается что A380 более прост в управлении. Об этом говорит даже тот факт что экипаж A380 составляет два человека (против 4 человек в Ту-154М).

A380

Аналоговых приборов почти не осталось, им на смену пришли цифровые приборы и LCD панели. Рычаги управления стали больше похожи на джойстик. Основным органом управления, судя по всему, стала клавиатура. Но стал ли он проще? Для пилотов может быть, для всех остальных никакой разницы. Если вы чувствуете себя как слон в посудной лавке в кабине Ту-154, тоже самое будет в кабине A380.

Конечно, если вы можете создать продукт который будет решать задачи пользователя и при этом будет простым как электрочайник, то это просто прекрасно. Но есть сферы где человеку нужен полный контроль над происходящим и масса информации чтобы принять верное решение. И в этом случае может быть не лучшей идеей сводить интерфейс к одной кнопке в UI/одному методу в API и т.д.

Простота многомерна

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

Простота использования

Если речь идет об API или бибилиотеке, то как просто ее развернуть на клиенте и начать использовать?

Простота написания

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

Простота тестирования

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

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

Простота верификации

Автоматическое тестирование не панацея конечно же, особенно если мы говорим о параллельных приложениях, которые очень тяжело тестировать. Насколько просто вы можете загрузить в голову коллеги такую ментальную модель при помощи которой он мог бы сказать: “да, я уверен, этот код работает”? Это и есть простота верификации.

Простота понимания

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

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

Проблема в том, что упрощений в чистом виде не так много. Чаще приходится иметь дело с разменом. Упрощая одно, вы автоматически усложняете другое. Например, упрощение тестирования зачастую связанно с “расслоением” системы и усложнением ее понимания. Это размен на который мы идем, неважно отдаем мы себе в этом отчет или нет. Вопрос в том, выгоден ли этот размен для нас? Но это тема совсем другого разговора…