О читабельности

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

Наши коллеги или Интернет снова и снова говорят нам, что удобочитаемость важна, но термин «удобочитаемость» определяется очень расплывчато. Разные люди, как правило, имеют разные представления о том, какой код легче читать, чем другие. Я не буду пытаться заставить вас принять мое определение удобочитаемости, а скорее приведу несколько примеров, когда неправильная практика кодирования делает программу трудной для понимания и, следовательно, заставляет разработчиков работать с ней гораздо больше времени, чем необходимо.

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

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

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

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

Мне не жаль, что я не сказал вам, что вам не нужно читать весь код выше, вам нужно почувствовать боль. После прочтения первых 30 строк или около того у вас возникает идея, что это проверка состояния топливного бака. Где-то на 100 строчке вы поняли, что погода проверяется. Вам потребовалось около 20 минут, чтобы понять, какие компоненты должны включать предполетную проверку. Теперь прочитайте этот код:

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

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

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

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

Ввод validateInput здесь лжет вам в лицо, потому что он выполняет проверку и выдает HTTP-запрос для фактической отправки формы, хотя он утверждает, что делает только первое. Почему это плохо? Потому что когда вы читаете код в submitButtonPressed, вы теряетесь. Кажется, что когда пользователь нажимает кнопку отправки, все, что происходит, — это проверка ввода, и это сбивает с толку. Когда запрос действительно отправляется? Вам нужно его подать? Есть ли какая-нибудь асинхронная служба, которая позаботится об этом автоматически? Вы не узнаете, пока не изучите метод validateInput. Подобные функции сильно ухудшают читабельность, поскольку они создают дыры в вашем потоке чтения, делая что-то неявно. Чтение такого кода занимает гораздо больше времени и усилий. Для сравнения, приведенный ниже код читается лучше, когда validateInput ничего не делает неявно (не имеет побочного эффекта).

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