Статьи

Соглашения о кодировании Java считаются вредными

На сайте Oracle опубликовано официальное Соглашение о коде для руководства по языку программирования Java . Вы ожидаете, что этот документ на 20 с лишним страниц станет наиболее полным, всеобъемлющим и авторитетным источником передового опыта, советов и подсказок в отношении языка Java. Но как только вы начинаете читать это, разочарование, сопровождаемое разочарованием и гневом, увеличивается. Я хотел бы указать на наиболее очевидные ошибки, плохую практику, плохие и устаревшие советы, данные в этом руководстве. Если вы новичок в Java, просто забудьте об этом руководстве и поищите лучшие и более свежие справочные материалы. Пусть начнется ужас! 2.2 Общие имена файлов :

GNUmakefile Предпочтительное имя для make-файлов. Мы используем gnumake для создания нашего программного обеспечения. gnumake для создания проектов Java? Муравей считается олдскулом, а мавен — Кто использует make для создания WAR, JAR, генерации JavaDocs …? 3.1.1 Начальные комментарии : Все исходные файлы должны начинаться с комментария в стиле c, в котором перечислены имя класса, информация о версии, дата и уведомление об авторских правах. Поместить имя класса в комментарий, начиная файл? Что если я передумаю и переименую класс позже? И что должна представлять эта « дата »? Некоторые люди используют различные заполнители для автоматической вставки времени последнего изменения файла системой контроля версий. Ну, VCS здесь, чтобы сказать вам, когда файл был создан или последний раз изменен — ​​и изменение одной и той же строки снова и снова делает слияние огромной болью. 4 — Отступ : в качестве единицы отступа должны использоваться четыре пробела. Точная конструкция отступа (пробелы и табуляции) не указана. Вкладки должны быть установлены точно каждые 8 ​​пробелов (не 4). Вероятно, самая нелогичная часть документа. Некоторые предпочитают пробелы, другие (в том числе и я) — вкладки. Дело вкуса и командных договоренностей. Но это руководство предлагает использовать и то, и другое, иногда заменять пробелы символами табуляции. Это « не указано ». Мой совет: используйте вкладки и дайте каждому разработчику настроить его IDE так, чтобы он имел как можно большие, так и маленькие отступы.

4.1 Длина линии :

Избегайте строк длиной более 80 символов, так как они плохо обрабатываются многими терминалами и инструментами.

80 символов? Мой ноутбук легко помещается в три раза больше. Стремитесь к 120-140 символам в одной строке, но не используйте жесткие переносы. Лично я просто отображаю вертикальное поле и

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

И мы должны вписать всю строку в 80 символов?

5.1.2 Однострочные комментарии :

1
2
3
4
5
if (condition) {
 
    /* Handle the condition. */
    ...
}

На случай, если код недостаточно информативен, я предлагаю еще лучший комментарий:

1
2
3
4
5
if (condition) {
 
    /* This block is executed if condition == true. */
    ...
}

5.1.3 Конечные комментарии :

1
2
3
4
5
if (a == 2) {
    return TRUE;            /* special case */
} else {
    return isPrime(a);      /* works only for odd a */
}

Вы имели в виду (и не говорите мне, что это менее читабельно, даже без комментариев)?

1
return a == 2 || isPrime(a);

6.1 Количество в строке :

1
2
int level; // indentation level
int size;  // size of table

Зачем использовать описательные имена переменных, когда у нас есть комментарии ! Рассмотрим это вместо этого:

1
2
int indentationLevel;
int tableSize;

Далее в этом разделе: ни в коем случае нельзя объявлять переменные и функции в одной строке. Пример:

1
long dbaddr, getDbaddr(); // WRONG!

Конечно, это неправильно, он даже не компилируется. Я удивлен, что « не ставьте пробелы в именах переменных » не упоминается как хорошая практика…

6.3 Размещение :

Размещайте объявления только в начале блоков. […] Не ждите объявления переменных до их первого использования; это может запутать неосторожного программиста […] Вот как соглашения о кодировании хотят, чтобы вы писали свой код:

01
02
03
04
05
06
07
08
09
10
int min;            //inclusive
int max;            //exclusive
int distance;
List<String> list;  //one per each item
 
min = findMin();
max = findMax();
distance = max - min;
list = new ArrayList<>(distance);
//...

И вот как это должно быть написано, чтобы избежать путаницы:

1
2
3
4
5
final int minInclusive = findMin();
final int maxExclusive = findMax();
final int distance = maxExclusive - minInclusive;
final List<String> listOfItems = new ArrayList<>(distance);
//...

Кроме того, мы можем, наконец, ( nomen est omen ) использовать ключевое слово final . Далее в этом разделе приведен пример кода с полями класса, в которых отсутствует private модификатор (по умолчанию, закрытый доступ к пакету). Пакет приватного поля?

7.3 Заявления о возврате :

1
return (size ? size : defaultSize);

Возможно, вы не заметили, но из контекста мы можем сказать, что и size и defaultSize имеют boolean тип. Правильно, size и defaultSize могут быть как true и false (!) Как это нелогично! От такого документа я бы ожидал не только синтаксической правильности, но и значимого кода и хороших практик! Более того, выражение может быть значительно упрощено, шаг за шагом :

1
2
3
size ? size : defaultSize
size ? true : defaultSize
size || defaultSize

7.5 для заявлений :

Пустой оператор for (в котором вся работа выполняется в предложениях инициализации, условия и обновления) должен иметь следующую форму:

1
for (initialization; condition; update);



пусто for выписки ? Зачем вам когда-либо использовать пустое for заявления? Это сбивает с толку, и его следует избегать, а не поощрять и описывать в официальном руководстве по языку.

Бонус викторина: какова цель этого кода в C?

1
while(*dst++ = *src++);

Я считаю, что каждый программист должен понимать фрагмент кода выше. Даже если вы программируете на Ruby или TSQL.

7.8 Заявления переключателя :

Каждый раз, когда case проваливается (не содержит оператора break ), добавьте комментарий там, где обычно был бы оператор break .


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

8.1 Пустые строки :

Одна пустая строка всегда должна использоваться при следующих обстоятельствах:

[…]

  • Между локальными переменными в методе и его первым оператором
  • Перед блоком […] или однострочным комментарием […]
  • Между логическими разделами внутри метода для улучшения читабельности


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

Размещение пустой строки между объявлениями переменных и первым оператором звучит так, как будто они взяты из книги по языку Си.

8.2 Пробелы :

  • Все бинарные операторы, кроме . должны быть отделены от своих операндов пробелами. Пробелы никогда не должны отделять унарные операторы, такие как унарный минус, приращение (‘ ++ ‘) и декремент (‘ -- ‘), от их операндов. Пример:

[…]

1
2
3
while (d++ = s++) {
  n++;
}

Это даже не компилируется в Java …

9 — Соглашения об именах (только в PDF-версии ):

1
char *cp;

Хорошее имя для указателя на char в Java — cp . Подожди, ЧТО ? указатель на char в Java?

10.1 Предоставление доступа к переменным экземпляра и класса :


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

10.4 Назначения переменных :

1
2
3
if (c++ = d++) {        // AVOID! (Java disallows)
    ...
}

Хороший совет: пожалуйста, избегайте использования конструкций, которые даже не компилируются в Java. Это делает нашу жизнь намного проще!

10.5.2 Возвращаемые значения :

1
2
3
4
5
if (booleanExpression) {
    return true;
} else {
    return false;
}

вместо этого должно быть написано как

1
return booleanExpression;

Святая корова, я согласен!

Резюме

Дело не в том, что официальные соглашения о коде для языка программирования Java полностью неверны. Они просто устарели и устарели. Во втором десятилетии XXI века у нас лучшее оборудование, более глубокое понимание качества кода и более современные источники мудрости . Соглашения о коде … в последний раз были опубликованы в 1999 году, они основаны на языке C и не знают о миллиардах строк кода, которые еще предстоит написать миллионам разработчиков. Соглашения о коде должны появляться со временем, точно так же, как шаблоны проектирования, а не передаваться явно. Поэтому, пожалуйста, не цитируйте и не следуйте советам официального руководства.

Ссылка: Соглашения о кодировании Java, считающиеся вредоносными, от нашего партнера по JCG Томаша Нуркевича в блоге, посвященном Java и соседству .