Написание хорошего Java-кода

Введение в Java-код

Вы уже знаете достаточно много о синтаксисе Java, но это не совсем то, в чем заключается профессиональное программирование. Что делает Java-программы «хорошими»?

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

По правде говоря, я являюсь сторонником agile-методов (динамичных методов), таких как Экстремальное Программирование (Extreme Programming — XP), поэтому многое в моих представлениях о «хорошем» коде сформировано agile-сообществом и, в частности, принципами XP. Тем не менее, я считаю, что большинство опытных профессиональных Java-программистов согласилось бы с советами, которые я дам в данном разделе.

Делайте классы маленькими

В данном руководстве мы создали простой класс Adult . Даже после того, как мы переместили метод main() в другой класс, Adult имел более 100 строк кода. Он имеет более 20 методов, и, в действительности, выполняет не много работы в сравнении со многими профессионально созданными классами, которые вы, вероятно, видите (и создаете). Это маленький класс.

Нередко можно увидеть классы с числом методов от 50 до 100. Что делает их хуже классов, имеющих меньшее число методов? Наверное, ничего. Должно быть столько методов, сколько вам нужно. Если вам нужно несколько вспомогательных методов, выполняющих, в основном, одинаковую работу, но принимающих различные параметры (как наши методы addMoney() ), — это прекрасный вариант. Просто ограничивайте список методов только теми, которые действительно нужны, не более.

Обычно класс с очень большим числом методов содержит нечто, ему не свойственное, поскольку такой гигантский объект делает слишком много. В своей книге «Рефакторинг» Мартин Фаулер (Martin Fowler) называет это «загрязнением кода чуждыми методами» (Foreign Method code smell). Если у вас есть объект со 100 методами, вы должны хорошо подумать, не является ли этот один объект в действительности комбинацией нескольких объектов. Большие классы обычно отстают в школе. То же самое касается и Java-кода.

Делайте методы маленькими

Маленькие методы также предпочтительны, как и маленькие классы, и по тем же причинам.

Одним из огорчений, которые есть у опытных ОО-программистов в отношении языка Java, является то, что он дает широким массам пользователей объектно-ориентированный подход, но не учит их, как им правильно пользоваться. Другими словами, он дает достаточно веревки, чтобы повеситься (хотя и меньше, чем дает C++). Обычно это можно увидеть в классе с методом main() длиной в пять миль, или в одном методе под названием doIt() .

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

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

Ограничивайте каждый метод до производительности одного действия.

Называйте методы правильно

Лучшая из когда-либо встреченных мной схем кодирования (и я забыл источник) называется: обнаруживающие намерения имена методов. Какой из двух следующих методов легче понять с первого взгляда?

  • a()
  • computeCommission()

Ответ должен быть очевидным. По некоторым причинам программисты испытывают антипатию к длинным именам. Конечно, абсурдно длинное имя может быть неудобным, но достаточная для понимания длина имени обычно не является абсурдно большой. У меня нет проблем с таким именем метода, как aReallyLongMethodNameThatIsAbsolutelyClear() . Но если в три часа ночи, пытаясь понять, почему моя программа не работает, я встречаю метод с названием a() , то хочу кого-нибудь ударить.

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

if (myAdult.getWallet().isEmpty()) { 	  do something   }

Метод isEmpty() объекта ArrayList полезен сам по себе, но это условие в нашем выражении if можно улучшить, применив метод Adult с названием hasMoney() , который выглядит следующим образом:

public boolean hasMoney() { 	return !getWallet().isEmpty(); }

Теперь наше выражение if больше похоже на английский:

if (myAdult.hasMoney()) { 	  do something   }

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

Минимизируйте количество классов

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

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

Почти во всех моих Java-проектах никто не боялся создавать классы, но мы также постоянно пытались уменьшить количество классов, не делая наши намерения менее ясными.

Минимизируйте количество комментариев

Я когда-то писал обширные комментарии в моих программах. Вы могли читать их как книгу. Потом я стал немного умнее.

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

Мое практическое правило: если код настолько тяжело прочитать и понять, что нужен комментарий, я должен сделать его достаточно понятным, для того чтобы комментарий был не нужен. Код может быть слишком длинным, или делать слишком много. Если это так, я упрощаю его. Он может быть слишком запутанным. Если это так, я добавляю вспомогательные методы, для того чтобы сделать его более понятным.

Фактически, за три года совместного программирования на Java с участниками одной и той же команды я могу пересчитать количество написанных мной комментариев на пальцах моих рук и ног. Пишите понятный код! Если вам необходимо общее описание того, что делает система или какой-то конкретный ее компонент, напишите краткий документ для этого.

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

Используйте унифицированный стиль

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

public void myMethod() { 	if (this.a == this.b) 	{ 		  statements   	} }

Почему он раздражает меня? Потому что я лично против стиля кодирования, при котором добавляются строки кода, по моему мнению, не нужные. Java-компилятор интерпретирует следующий код аналогично предыдущему, а я сохранил несколько строк:

public void myMethod() { 	if (this.a == this.b) 		  statements   }

Нет способа «правильного» или «неправильного». Один просто короче другого. Что же происходит, когда мне приходится кодировать вместе с тем, кто предпочитает первую форму? Мы говорим об этом, выбираем стиль кодирования, который собираемся придерживаться, затем фиксируем его. Единственным правилом на все случаи жизни является унификация. Если кто-то из работающих над проектом использует другой стиль, чтение кода станет трудным. Выберите стиль и не меняйте его.

Избегайте использования операторов switch

Некоторые Java-программисты любят выражения switch . Я думал, что они хороши, но потом понял, что выражение switch на самом деле является просто набором выражений if ; это обычно означает, что условная логика появляется в моем коде более чем в одном месте. Это дублирование кода, что недопустимо. Почему? Потому что присутствие одинакового кода в нескольких местах затрудняет его изменение. Если у меня есть один и тот же switch в трех местах, и нужно изменить один вариант, я должен поменять три фрагмента кода.

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

Будьте открыты

Я оставил самые сомнительные рекомендации напоследок. Вдохните глубже.

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

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

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

Такого рода разочарование часто наступает при использовании чужого кода. Вы можете увидеть метод, делающий точно то, что вам нужно, но он не доступен. Иногда есть веские причины этого, поэтому имеет смысл ограничить доступность. Однако иногда единственной причиной того, что метод не указан как public , является то, что парни, написавшие код, думали: «Никому и никогда даже не понадобиться обратиться к нему». А может они думали: «Никто не должен обратиться к нему, потому что…», вовсе не имея серьезной на это причины. Очень часто люди используют ключевое слово private только потому, что оно существует. Не поступайте так.

Указывайте методы как public , а переменные как protected , если не имеете серьезной причины для ограничения доступа.

По следам Фаулера (Fowler)

Теперь вы знаете, как создавать хороший Java-код и как поддерживать его хорошим.

Лучшей книгой по этой теме является «Рефакторинг» Мартина Фаулера (Martin Fowler). Ее даже читать легко. Рефакторинг означает изменение дизайна существующего кода без изменения его результатов. Фаулер говорит о «загрязнениях кода» («code smells»), которые требуют рефакторинга, и очень подробно рассматривает различные технические приемы для их исправления.

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

Писать Java-код относительно не сложно. Писать хороший Java-код — это мастерство. Стремитесь стать мастером.

Рейтинг
( 1 оценка, среднее 5 из 5 )
Загрузка ...