Я хочу обсудить то, что, на мой взгляд, является одним из величайших грехов профессии программиста. Я начну с личной истории, чтобы подготовить почву.

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

Технический руководитель продолжал отвергать код в моих PR, который не соответствовал правилу чистого кода, даже в нескольких конкретных ситуациях, когда я думал, что код определенно чище с ранним возвратом. Итак, я начал сомневаться в этом. Я спросил: Почему у нас есть это правило, почему иметь несколько операторов возврата - это плохой код? Я получил несколько пренебрежительный ответ: Это признанный стандарт кодирования в индустрии программного обеспечения, вы всего лишь младший разработчик, который еще не знаком с ним ...

Меня это не убедило, и через несколько дней я снова настоял на своем. Наконец я получил больше информации: это правило исходило от самого Дейкстры, известного компьютерного ученого, который записал его в книге. Теперь я был заинтригован… но все еще не полностью убежден. Я поискал его, и действительно, Дейкстра по существу сказал: каждая функция и каждый блок внутри функции должны иметь одну запись и один выход. Это называется принципом единого входа, единственного выхода и изначально был написан в Структурированном программировании (в 1972 году!).

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

Итак, что здесь происходило 🤔?… На самом деле это правило было, цитируя StackOverflow: написано, когда большая часть программирования выполнялась на языке ассемблера, FORTRAN или COBOL, что означает, что основной контекст сильно отличался от контекста в моя компания. Это правило было направлено на решение проблем, которые возникали только на языках , поддерживающих goto. (см. 1-й ответ на StackOverflow для цитируемой цитаты)

В разумной степени это правило кодирования все еще применяется к языку C, потому что, как описано во 2-м ответе StackOverflow, множественные возвраты в функции затрудняют обеспечение очистки ресурсов. Я считаю, что именно здесь мой технический руководитель узнал об этом правиле, так как он начинал как программист на C, и это упоминалось в нескольких книгах по C, особенно в MISRA C - известном стандарте кодирования C.

Однако ничего из этого больше не применимо в мире Java или в подобных объектно-ориентированных языках. В современных объектно-ориентированных языках есть сборка мусора, поэтому подавляющее большинство ресурсов не нужно явно закрывать / освобождать. Даже для ресурсов, которые это делают (файлы, сокеты, потоки и т. Д.), Есть блок finally, который поможет с этим. Другими словами, контекст правила настолько изменился, что он больше не применялся - и, возможно, это ухудшило код! (Эта статья о Раннем возвращении имеет более подробное обоснование)

Так к чему я к этому иду? Надеюсь, теперь мораль истории должна быть ясна:

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

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

Для Java и OO подумайте, например, о том, что все поля в классах должны всегда быть закрытыми и доступными для геттеров. Для REST ваш сервисный API должен в идеале достичь уровня 2 или более в модели зрелости Ричардсона (что мне делать с HTTP-командами и кодами состояния, если я хочу предоставить адаптер gRPC?). Что касается процессов управления и разработки, то есть Agile… что является огромным минным полем неправильного применения принципов. Вероятно, потому, что контекст для гибкой разработки намного более тонкий, сложный и субъективный. Но не будем вдаваться в подробности ...

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

Одно связующее примечание: идея понимания контекста и обстоятельств правил и рекомендаций тесно переплетается с еще более общим принципом: Большая часть высокоуровневой разработки программного обеспечения связана с пониманием торговли: и делать выбор на основе этих компромиссов. Эта идея компромиссов обычно более ясна в архитектурных паттернах (например, микросервисах, источнике событий, CQRS и т. Д.), Поскольку в этих обсуждениях компромиссы и альтернативы, как правило, упоминаются явно . Другими словами, контекст проблемы более ясен.

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

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