Короткий підсумок найкращих практик кодування Java

на основі стандартів кодування від Oracle, Google, Twitter та Spring Framework

Мета цієї статті - дати вам короткий підсумок роботи і не інакше кажучи, віддайте перевагу та уникайте на основі стандартів кодування від технічних гігантів, таких як Oracle, Google, Twitter та Spring Framework.

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

Чому стандарти кодування в першу чергу? Є багато вагомих причин, якщо ви Google це, і я залишу вам наступну ілюстрацію

Документ зі стандартами кодування може бути тривалим і нудним. У цій статті вишня вибирає шматочки та шматочки з конвенцій про кодування від Google, Oracle, Twitter та Spring, і її мета - надати вам простий у дотриманні та менш нудний набір практик, щоб зробити ваш код легким для читання та обслуговування.

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

Давайте поглибимось кращими практиками з різних стандартів кодування.

Вихідний файл Java

Далі розглядається найкраща практика, коли мова йде про вихідні файли java:

  • Довжина вихідного файлу менше 2000 рядків коду
  • Вихідний файл організовується з коментарями до документації, декларацією пакета, а потім коментарем класу, груповим імпортом (статичний останній), підписом класу / інтерфейсу тощо, як показано нижче
пакет com.example.model;
/ **
 * Безкоштовна перспектива, яку слід читати розробникам
 * який може не обов’язково мати під рукою вихідний код
 *
 * @author x, y, z
 * @дата
 * @версія
 * @ авторські права
 *
 * /
імпортувати com.example.util.FileUtil;
/ *
 * Необов’язковий коментар до класу
 *
 * /
публічний клас SomeClass {
  // Статичні змінні в порядку видимості
  загальнодоступний статичний кінцевий цілий показник PUBLIC_COUNT = 1;
  статичний кінцевий цілий число PROTECTED_COUNT = 1;
  приватний статичний кінцевий цілий число PRIVATE_COUNT = 1;
  // Змінні екземпляри в порядку видимості
  загальна назва струни;
  Рядок PostalCode;
  приватна рядкова адреса;
  // Конструктор і перевантажений у послідовному порядку
  public SomeClass () {}
  public SomeClass (Назва рядка) {
    this.name = ім'я;
  }
  // Методи
  public String doSomethingUseful () {
    повернути «Щось корисне»;
  }
  // getters, setters, equals, hashCode та toString в кінці
}

Іменування

Назви класів та інтерфейсів - це CamelCase, і рекомендується використовувати ціле слово та уникати абревіатур / скорочень. Наприклад, клас Raster або клас ImageSprite

  • Пакет - імена com.deepspace над com.deepSpace або com.deep_space
  • Імена файлів є CamelCase і закінчуються .java, що відповідає імені класу. Існує один загальнодоступний клас на файл із кожним класом верхнього рівня у своєму файлі
  • Метод - імена повинні бути дієсловами у змішаному відмінку з кожним внутрішнім словом з великої літери, наприклад run (); або runFast ();
  • Константи - повинні бути великими літерами з символом "_", що розділяє кожне слово, наприклад, int MIN_WIDTH = 44; і int MAX_WIDTH = 99;
  • Змінна - назва, яка повідомляє читачеві програми, що являє собою змінна, тобто якщо ви зберігаєте тестовий клас, тоді виберіть клас проти var1. Тримайте імена змінних короткими, уникайте метаданих.
// Віддати перевагу () - короткі назви змін і описують, що він зберігає
int schoolId;
int [] filteredSchoolIds;
int [] унікальніSchooldIds;
Карта <Цілий, Користувач> usersById;
Значення рядка;
// Уникати (x) - Занадто детальне називання змінної
int schoolIdentificationNumber;
int [] userProvidedSchoolIds;
int [] schoolIdsAfterRemovingDuplicates;
Карта <Цілий, Користувач> idToUserMap;
Значення рядкаString;

Пам'ятайте - ім'я змінної повинно бути коротким і легко повідомляти читачеві, яке значення воно представляє. Використовуйте своє судження.

Віддавайте перевагу та уникайте

Форматування та відступ - це організація вашого коду, щоб його було легко читати, і він включає проміжки, довжину рядка, обгортання та перерви тощо.

  • Відступ - Використовуйте 2 або 4 пробіли та залишайтеся послідовними
  • Довжина рядка - До 70 - 120 символів, залежно від впливу на читаність. Важливо усунути необхідність горизонтальної прокрутки та розміщення розривів рядків після коми та оператора.

Методи - Ось перелік найкращих практик

// Віддати перевагу () Розриви рядків довільні та розрив після коми.
Завантаження рядківAnInternet (Інтернет в Інтернеті, трубки,
    Блоги блогосфери, сума <Довго, Дані> пропускна здатність) {
  tubes.download (Інтернет);
}
// Уникайте (x) важких для розходження аргументів методу до тіла методу
Завантаження рядківAnInternet (Інтернет в Інтернеті, трубки,
    Блоги блогосфери, сума <Довго, Дані> пропускна здатність) {
    tubes.download (Інтернет);
}
// Віддавайте перевагу () Додайте 8 (двічі з 2 або 4) пробілів для глибокого відступу
приватне статичне синхронізоване horkingLongMethodName (int anArg,
        Об'єкт іншогоArg, String yetAbodyArg,
        Object andStillAbody) {
  ...
}
// Віддайте перевагу () Просте сканування та додатковий простір стовпців.
загальнодоступна завантаження рядківAnInternet (
    Інтернет-Інтернет,
    Трубки трубочки,
    Блоги блогосфери,
    Сума <Довга, Дані> пропускна здатність) {
  tubes.download (Інтернет);
  ...
}
Одиничне випробування могло б наздогнати це

Якщо перевірки - IMO, що пише добре відформатований код, дозволяє легко помітити помилки друку та помилки автору та рецензентам коду, див. Нижче:

// Уникайте (x) Не опускайте {}
якщо (умова)
  заява;
// Уникати (x)
якщо (x <0) від'ємний (x);
// Уникати (x)
якщо (a == b && c == d) {
...
}
// Віддавайте перевагу ()
якщо ((a == b) && (c == d)) {
...
}
// Віддавайте перевагу ()
якщо (умова) {
  заяви;
} else if (умова) {
  заяви;
} else if (умова) {
  заяви;
}
// Уникати (x)
if ((умова1 та умови2)
    || (умова3 та умови4)
    ||! (condition5 && condition6)) {// BAD WRAPS
    doSomething AboutIt (); // ЗРОБИТИ ЦІЙ ЛІНІЙ ЛЕГКО МИСЛИЙ
}
// Віддавайте перевагу ()
if ((умова1 та умови2)
        || (умова3 та умови4)
        ||! (умова5 та умови6)) {
    doSomething AboutIt ();
}

Термінальний оператор - і нижче, рекомендуються практики

альфа = (aLongBooleanExpression)? бета: гамма;
альфа = (aLongBooleanExpression)? бета-версія
        : гамма;
альфа = (aLongBooleanExpression)
        ? бета-версія
        : гамма;

Перемикач - коли потрібно перейти до найкращої практики

  • Завжди мати регістр за замовчуванням, навіть без коду
  • Використовуйте / * пропадає через * /, щоб вказати, що контроль падає до наступного випадку
перемикач (умова) {
  випадок ABC:
    заяви;
  / * провалюється через * /
  випадок DEF:
    заяви;
    перерва;
  за замовчуванням:
    заяви;
     перерва;
}

Повідомлення про винятки - коли викидаєте виняток, тут наводяться зразки хороших та погано відрезаних повідомлень.

// Уникайте (x) - Не легко читати
кинути новий IllegalStateException ("Не вдалося обробити запит" + request.getId ()
    + "для користувача" + user.getId () + "query: '" + query.getText ()
    + "'");
// Віддавайте перевагу () - досить легше читати
кинути нову IllegalStateException ("Не вдалося обробити"
    + "запит" + request.getId ()
    + "для користувача" + user.getId ()
    + "query: '" + query.getText () + "'");

Ітератори та потоки. Потоки стають все більш поширеними, а часом вони можуть бути дуже складними, тому важливо відступити для легкого читання.

// Уникайте (x) - Не легко читати
Ітерабельні модулі  = ImmutableList.  builder (). Add (новий LifecycleModule ())
    .add (новий AppLauncherModule ()). addAll (application.getModules ()). build ();
// Віддавайте перевагу () - досить легше читати
Ітерабельні модулі  = ImmutableList.  builder ()
    .add (новий LifecycleModule ())
    .add (новий AppLauncherModule ())
    .addAll (application.getModules ())
    .build ();
Просто дотримуйтесь стандарту кодування - будь-який насправді

Декларації та призначення - рекомендується одна декларація за рядок, оскільки вона заохочує коментарі, як показано нижче.

// Віддавайте перевагу ()
рівень int; // рівень відступу
int sizeMeter; // розмір таблиці
// Уникайте (х) на користь вище
рівень int, sizeMeter;
// Віддати перевагу () - включення одиниці до назви змінної або типу
тривалий опитуванняІнтервалМ;
int fileSizeGb;
Сума <Ціле число, Дані> Розмір файлу;
// Уникайте (x) типів змішування
int foo, fooarray [];
// Уникати (x) - не розділяти комою
Format.print (System.out, "помилка"), вихід (1);
// Уникайте (x) багаторазового призначення
fooBar.fChar = barFoo.lchar = 'c';
// Уникайте (x) вбудованих завдань, намагаючись підвищити продуктивність // або зберегти рядок. Я винен у цьому :(
d = (a = b + c) + r;
// Віддавайте перевагу () вище
a = b + c;
d = a + r;
// Віддавайте перевагу ()
String [] аргументи
// Уникати (x)
Строкові аргументи []
// Віддайте перевагу () Тривале використання "L" замість "l", щоб уникнути плутанини з 1
тривалий час очікування = 3000000000L;
// Уникати (x) - важко сказати, що остання літера є l, а не 1
тривалий час очікування = 3000000000л;

Розміщуйте декларації лише на початку блоків (Блок є кодом, оточеним фігурними дужками {і}). Не чекайте оголошення оголошень змінних до їх першого використання; це може заплутати необережного програміста і перешкоджати переносу коду в межах області.

// Переважно () оголосити на початку блоку.
публічна недійсність doSomething () {
  int whatIRepresent; // початок блоку методу
  якщо (умова) {
    int someFlag; // початок блоку "якщо"
    …
  }
}

Також важливо уникати місцевих декларацій, які приховують декларації вищих рівнів, і уникати плутанини, як показано нижче

int count;
...
публічна недійсність doSomething () {
  якщо (умова) {
    int count; // УНИКНУЙТЕ!
    ...
  }
  ...
}

Пробіли та розриви рядків - уникайте спокуси збереження 1–2 рядків коду за рахунок читабельності. Ось усі найкращі практики щодо розбіжності та порожніх рядків (пробіл має значення)

  • Один (1) порожній рядок між методами та розробниками Spring рекомендує два (2) порожні рядки після конструкторів, статичний блок, поля та внутрішній клас
  • Оператори космічних майданчиків, тобто використовувати int foo = a + b + 1; над int foo = a + b + 1;
  • Відокремте всі бінарні оператори, крім ".", Від операндів, що використовують пробіл
  • Відкрита дужка "{" з'являється в кінці того самого рядка, що і декларація заяви, або метод, а закриваюча дужка "}" починає рядок сам по собі з відступу
// Prefer () - пробіл після "while" і раніше "("
в той час як (правда) {
  ...
}
// Уникати (x) - На відміну від вище немає місця
в той час як (правда) {
  ...
}
// Prefer () - Немає пробілу між "doSomething" і "("
public void doSomething () {
  ...
}
// Уникати (x) - на відміну від простору вище
публічна недійсність doSomething () {
  ...
}
// Prefer () - додайте пробіл після аргументу
public void doSomething (int a, int b) {
  ...
}
// Prefer () - Простір між операндом і операторами (тобто +, =)
a + = c + d;
a = (a + b) / (c * d);
while (d ++ = s ++) {
  n ++;
}

Документація та коментарі

Варто зазначити, що майже весь код змінюється протягом усього життя, і коли ви або хтось намагатиметься зрозуміти, що має на увазі складний блок коду, метод чи клас, якщо чітко не описано. Реальність майже завжди така, як випливає

Бувають випадки, що коментар до складного фрагмента коду, методу, класу не додає ніякого значення або не виконує його призначення. Зазвичай це відбувається, коментуючи заради цього.

Коментарі слід використовувати для огляду коду та надання додаткової інформації, яка недоступна в самому коді. Давайте розпочнемо. Існує два типи коментарів

Коментарі щодо впровадження - покликані коментувати код або коментувати певну реалізацію коду.

Коментарі до документації - призначені для опису специфікації коду з точки зору вільної реалізації, який слід читати розробникам, які не обов'язково мають під рукою вихідний код.

Частота коментарів іноді відображає низьку якість коду. Коли ви відчуваєте вимушеність додати коментар, спробуйте переписати код, щоб зробити його зрозумілішим.

Типи коментарів щодо впровадження

Існує чотири (4) типи коментарів щодо впровадження, як показано нижче

  • Блокувати коментар - див. Приклад нижче
  • Однорядковий коментар - коли коментар не довший, ніж рядок
  • Останні коментарі - дуже короткий коментар перемістився до правильного кінця
  • Коментар в кінці рядка - починається коментар, який продовжується до нового рядка. Він може коментувати повний рядок або лише частковий рядок. Він не повинен використовуватися в декількох послідовних рядках для текстових коментарів; однак він може бути використаний у послідовних кількох рядках для коментування розділів коду.
// Заблокувати коментар
/ *
 * Використання: надає опис файлів, методів, структур даних
 * та алгоритми. Можна використовувати на початку кожного файлу та
 * перед кожним методом. Використовується для тривалих коментарів, які не відповідають а
 * один рядок 1 Порожня лінія для продовження після блокування коментаря.
 * /
// Однорядковий коментар
якщо (умова) {
 / * Обробляйте умову. * /
  ...
}
// Останній коментар
якщо (a == 2) {
 повернути ПРАВИЛЬНО; / * особливий випадок * /
} else {
 повернення єPrime (a); / * працює лише для непарних * /
}
// Коментар у кінці рядка
if (foo> 1) {
  // Зробіть подвійний фліп.
  ...
} else {
  повернути помилкове; // Поясніть, чому тут.
}
// якщо (бар> 1) {
//
// // Зроби трійку.
// ...
//}
// інше
// повернути помилкове;

Коментарі до документації (тобто Javadoc)

Javadoc - це інструмент, який генерує HTML-документацію з вашого коду Java, використовуючи коментарі, що починаються з / ** і закінчуються * / - див. Вікіпедію для отримання більш детальної інформації про те, як працює Javadoc або просто читати далі.

Ось приклад Javadoc

/ **
 * Повертає об’єкт зображення, який потім можна намалювати на екрані.
 * Аргумент URL повинен вказувати абсолютний {@link URL}. Ім'я
 * аргумент - це специфікатор, що відповідає аргументу URL.
 * 

 * Цей метод завжди повертається негайно, незалежно від того  * зображення існує. Коли цей аплет намагається намалювати зображення  * на екрані дані будуть завантажені. Графічні примітиви  *, що малює зображення, поступово малюватиметься на екрані.  *  * @param url - абсолютна URL-адреса, яка визначає базове розташування зображення  * @param назвіть розташування зображення відносно аргументу URL-адреси  * @ поверніть зображення за вказаною URL-адресою  * @подивіться зображення  * /  загальнодоступне зображення getImage (URL-адреса, назва рядка) {         спробуйте {             повернути getImage (нова URL-адреса (URL, ім'я));         } лов (неправильнаURLException e) {             повернути нуль;         }  }

І вищезазначене призведе до HTML, як слід, коли javadoc запускається проти коду, який містить вище

Дивіться тут докладніше

Ось кілька ключових тегів, які можна використовувати для підвищення якості створеної документації на Java.

@author => @author Раф
@code => {@code A  C}
@deprecated => @depreposed deprecation-message
@exception => @exception IOException кинуто, коли
@link => {@link package.class # член мітки}
@param => Опис параметра-ім'я @param
@return => Що метод повертає
@see => @see "string" АБО @see  
@since => Щоб вказати версію, коли додано загальнодоступний метод

Повний перелік та більш детальний опис дивіться тут

Стандарт кодування Twitter захищає використання тегу @author

Код може міняти руки багато разів протягом свого життя, і досить часто оригінальний автор вихідного файлу не має значення після кількох ітерацій. Ми вважаємо, що краще довіряти історії введення файлів і власникам файлів, щоб визначити право власності на тіло коду.

Нижче наведено приклади того, як ви можете написати коментар до документації, який є проникливим, як описано у стандарті кодування Twitter

// Поганий.
// - Документ нічого не каже, що декларація методу не зробила.
// - Це 'doc doc'. Це пройшло б перевірку стилю, але
нікому не допомагає.
/ **
 * Розбиває рядок.
 *
 * @param s Рядок.
 * @return Список рядків.
 * /
Список  розділити (String s);
// Краще.
// - Ми знаємо, на що розбивається метод.
// - Ще якась невизначена поведінка.
/ **
 * Розбиває рядок на пробіл.
 *
 * @param s Рядок для розбиття. Рядок {@code null} трактується як порожній рядок.
 * @return Перелік розділених пробілами частин вводу.
 * /
Список  розділити (String s);
// Великий.
// - Покриває ще один крайній корпус.
/ **
 * Розбиває рядок на пробіл. Повторні символи пробілів
 * згортаються.
 *
 * @param s Рядок для розбиття. Рядок {@code null} трактується як порожній рядок.
 * @return Перелік розділених пробілами частин вводу.
 * /
Список  розділити (String s);

Щоб писати коментарі, важливо бути професійним

// Уникати (x)
// Я так ненавиджу xml / мило, чому він не може це зробити для мене !?
спробуйте {
  userId = Integer.parseInt (xml.getField ("id"));
} улов (NumberFormatException e) {
  ...
}
// Віддавайте перевагу ()
// TODO (Jim): Підтвердження поля в бібліотеці.
спробуйте {
  userId = Integer.parseInt (xml.getField ("id"));
} улов (NumberFormatException e) {
  ...
}

І важливо пам’ятати, що не документувати переосмислений метод, якщо впровадження не змінилося.

І ось ще кілька моментів, про які слід пам’ятати

  • Уникайте імпорту незамінних символів - як описано в стандартах кодування Twitter, це робить джерело класу менш зрозумілим. Я працюю в команді, яка поєднує користувачів Eclipse та IntelliJ, і я дізналася, що Eclipse видаляє імпорт підстановки і IntelliJ впроваджує її. Напевно, є варіант її вимкнути, просто хотілося вказати типово для двох.
  • Завжди використовуйте примітку @Override під час перестановки
  • Заохочуйте використовувати @Nullable, коли поле чи метод повертає нуль
  • Скористайтеся спеціальними коментарями для подальшої роботи і не забудьте залишити посилання на себе, щоб інші знали, кому задати своє питання Y замість того, щоб здогадуватися, видалити його або перевірити звинувачення в git, щоб знайти, хто додав його. Деякі IDE, такі як Eclipse та IntelliJ, також допомагають перелічити їх для легкого доступу, а також нагадування.
// FIXME (Raf): Дійсне повідомлення описує, що потрібно зробити
// TODO (Raf): Діяльне повідомлення описує, що потрібно зробити

Кінцева гра - це написання коду, який полегшить життя майбутніх авторів та технічних працівників.

Кінцева гра

Інші відповідні матеріали для читання

Перелік відповідних статей, які мають відношення до написання коду, який є чистим, добре структурованим, легким для читання та підтримкою. Якщо ви хочете прочитати більше, напевно рекомендую наступне

і ще один хороший список порад щодо написання чистого коду