Статьи

Вкладки против пробелов: как они пишут Java в Google, Twitter, Mozilla и Pied Piper

Каковы наиболее интересные моменты в популярных стилях кода Java?

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

doSomethingIf

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

В этой статье мы расскажем о правилах форматирования и различных стилях Java-кодирования в таких компаниях, как Google, Twitter, Mozilla, стандарт Java и наши собственные команды в Takipi.

Зачем использовать руководящие принципы в первую очередь?

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

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

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

  1. Руководство по стилю Google Java (есть еще одно для Android)
  2. Руководство по стилю Twitter
  3. Официальные соглашения Java-кода (новые руководства OpenJDK доступны прямо здесь )
  4. Руководство по Mozilla
  5. Наши собственные рекомендации в Такипи

Посмотрим, что у них в магазине.

1. Отступы: табуляция против пробелов

Во-первых, мы должны снять это с наших сундуков, прежде чем продолжить. В руководствах по стилю есть явное предпочтение пробелам над вкладками. Здесь мы не будем вдаваться в плюсы и минусы, а просто поделимся результатами:

Google: 2 пробела (у андроида 4 пробела и 8 для переносов строк)
Twitter: 2 или 4 пробела (для переносов строк)
Мозилла: 4 пробела
Java: 4 пробела, вкладки должны быть установлены на 8 пробелов. Оба приемлемы.

Возможно, разработчики, использующие вкладки, не любят писать руководства по стилю & # 55357; & # 56841;

Данные из Github предполагают, что около 10-33% репозиториев Java предпочитают вкладки, и большинство использует пробелы в разных формациях, предпочитая 4 пробела по сравнению с 2. На самом деле есть довольно хороший модуль для выполнения этого анализа (сравнения разных языков). Кстати, заглядывая в другие языки JVM, такие как Scala и Clojure, мы видим почти 100% 2 пробелов.

Учитывая больший набор данных, который охватывает отдельные коммиты, мы получили разные результаты ( проект анализа конвенций , один из победителей конкурса данных Github ), но мы можем оценить, что он находится где-то между, вероятно, ближе к 10%.

(Если вам было любопытно, в Такипи мы предпочитаем вкладки. Мы не варвары. Иди Ричард Хендрикс! )

tabsvsspaces-768x356
Java Tabs vs Spaces — Анализ популярных соглашений кода (Источник: outsideris / Popularconvention )

2. Длина строки, упаковка и разрывы

Иногда строки кода Java имеют тенденцию становиться длинными, и руководства по стилю устанавливают соглашения о том, когда уместно разбивать или переносить. Общее соглашение составляет около 80-100 макс. Длина

Google: 100 столбцов
Twitter: предпочтение 100 колонкам
Mozilla: соответствующее суждение
Java: 80 столбцов

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

Вот пример из руководства по стилю в твиттере, которое хорошо использует эту концепцию:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
// Bad.
//   - Line breaks are arbitrary.
//   - Scanning the code makes it difficult to piece the message together.
throw new IllegalStateException("Failed to process request" + request.getId()
    + " for user " + user.getId() + " query: '" + query.getText()
    + "'");
 
// Good.
//   - Each component of the message is separate and self-contained.
//   - Adding or removing a component of the message requires minimal reformatting.
throw new IllegalStateException("Failed to process"
    + " request " + request.getId()
    + " for user " + user.getId()
    + " query: '" + query.getText() + "'");

Это помогает разделить операторы и создать логику, в которой каждая строка кода представляет собой автономную / «атомарную» операцию. Руководства по стилю имеют тенденцию соглашаться здесь.

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

3. Переменная Naming

Широкое согласие всех руководств по стилю. FirstLetterUpperCase для имен классов camelCase для имен методов и переменных, все строчные имена пакетов и ALL_CAPS для конечных статических констант. Распространенным исключением для этого является регистратор, который мы обычно определяем как:

1
private static final Logger logger = LoggerFactory.getLogger(Class.class);

Руководство Твиттера добавляет еще один интересный стиль включения модулей в имена переменных:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
// Bad.
//   - Field names give little insight into what fields are used for.
class User {
  private final int a;
  private final String m;
 
  ...
}
 
// Good.
class User {
  private final int ageInYears;
  private final String maidenName;
 
  ...
}

4. Исключительные условия

Исключения являются сложным вопросом. Недавно мы рассмотрели исследование, в котором рассматривалось более 600 000 проектов на Github и Sourceforge, и раскрыли некоторые мрачные истины о нестандартном использовании исключений. Руководства по стилю Google и Twitter ссылаются на печально известные пустые блоки catch:

Google: нет пустых блоков catch
Twitter: Другими словами, не глотайте исключения
Mozilla: нет ссылки
Java: нет ссылки

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

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

5. Скобки для ясности и фигурные скобки

Даже если они не нужны, скобки могут помочь улучшить читаемость. С составными предикатами для ясности принято использовать круглые скобки, даже когда порядок выполнения очевиден. Например:

1
2
if (x == y && a > 10) // bad
if ((x == y) && (a > 10)) // good

Так что же говорят руководства по стилю о группировке скобок?

Google: «Рекомендуется»
Twitter: «Будьте откровенны» (даже если это очевидно)
Java: «Вообще хорошая идея»
Mozilla: следуя стандарту Java

При работе с фигурными скобками во всех руководствах по стилю проверяется разрыв поддержки после открывающей скобки. В Takipi мы на самом деле делаем обратное, но мы не одиноки, в то время как «встроенные» фигурные скобки используются большинством разработчиков Java, 37% проверенных здесь коммитов кода используют новую строку:

curlybraces-768x360
Стили операторов блока — Анализ популярных условных обозначений кода (Источник: outsideris / Popularconvention )

6. Нет мозгов внутри конструкторов

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

Если нам нужно создать объект и выполнить некоторые тяжелые операции для его создания, вместо этого мы используем метод создателя. Например:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/// simple constructor
//
private final int x;
private final int y;
private final String z;
 
public MyClass(int x, int y, String z) {
    this.x = x;
    this.y = y;
    this.z = z;
}
 
 
// complex building
//
public static MyClass create(List<Stuff> list, Set<Stuff> set) {
    // int x = some brains...
    // int y = more brains...
    // other brains...
    // String z = more complex stuff here
    //
    return new MyClass(x, y, z);
}
 
private final int x;
private final int y;
private final String z;
 
private MyClass(int x, int y, String z) {
    this.x = x;
    this.y = y;
    this.z = z;
}

Последние мысли

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

Каковы некоторые из уникальных руководящих принципов / причуд, которым вы следуете? Ваша компания / команда использует собственное руководство по стилю? Пожалуйста, не стесняйтесь поделиться ими в разделе комментариев ниже!