Кратко резюме на най-добрите практики за кодиране на 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;
  // Променливи за инстанция по ред на видимост
  обществено име на низ;
  String postalCode;
  личен стринг адрес;
  // Конструктор и претоварен в последователен ред
  обществен SomeClass () {}
  обществен 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 [] филтрираниSchoolIds;
int [] уникалниSchooldIds;
Карта  usersById;
Стоеща стойност;
// Избягвайте (x) - Прекалено подробно именуване на променлива
int schoolIdentificationNumber;
int [] userProvidedSchoolIds;
int [] schoolIdsAfterRemovingDuplicates;
Карта  idToUserMap;
String valueString;

Запомнете - името на променливата трябва да е кратко и лесно да казва на читателя каква стойност представлява. Използвайте преценката си.

Предпочитайте и избягвайте

Форматирането и отстъпите са свързани с организирането на вашия код, за да се улесни четенето и включва разстояние, дължина на реда, увивания и прекъсвания и т.н.

  • Отстъп - Използвайте 2 или 4 интервала и останете последователни
  • Дължина на реда - До 70 до 120 знака в зависимост от влиянието върху четливостта. Важно е да се премахне необходимостта от хоризонтално превъртане и поставяне на прекъсвания на линии след запетая и оператор.

Методи - Ето списък на най-добрите практики

// Предпочитам () Прекъсванията на редове са произволни и се прекъсват след запетая.
Изтегляне на струниAnInternet (интернет интернет, тръби за тръби,
    Блогосферни блогове, сума  bandwidth) {
  tubes.download (интернет);
}
// Избягвайте (x) Трудно различаващи се аргументи от метода към тялото на метода
Изтегляне на струниAnInternet (интернет интернет, тръби за тръби,
    Блогосферни блогове, сума  bandwidth) {
    tubes.download (интернет);
}
// Предпочитайте () Добавете 8 (двойно от 2 или 4) пространства за дълбок отстъп
частно статично синхронизирано horkingLongMethodName (int anArg,
        Обект на другArg, String yetAbodyArg,
        Object andStillAgether) {
  ...
}
// Предпочита () Лесно сканиране и допълнително пространство в колоните.
публично изтегляне на StringAnInternet (
    Интернет интернет,
    Тръби тръби,
    Блогосферни блогове,
    Сума  bandwidth) {
  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)
    ||! (условие5 && условие6)) {// BAD WRAPS
    doSomethingAboutIt (); // НАПРАВЕТЕ ТАЗИ ЛИНИЯ ЛЕСНО ЗА МИСЛЕНЕ
}
// Предпочитам ()
if ((условие1 && условие2)
        || (условие 3 & състояние4)
        ||! (условие5 && условие6)) {
    doSomethingAboutIt ();
}

Терминален оператор - И по-долу са препоръчителните практики

алфа = (aLongBooleanExpression)? бета: гама;
алфа = (aLongBooleanExpression)? бета
        : гама;
алфа = (aLongBooleanExpression)
        ? бета
        : гама;

Превключване - Когато става въпрос за превключване, това е най-добрата практика

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

Съобщения за изключения - Когато хвърляте изключение, тук са извадки от добри и лошо отредени съобщения.

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

Итератори и потоци - Потоците стават все по-често срещани и понякога могат да бъдат много сложни, затова е важно да се отстъпи за лесно четене.

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

Декларации и задания - препоръчва се по една декларация на ред, тъй като насърчава коментарите, както е показано по-долу.

// Предпочитам ()
int ниво; // ниво на вдлъбнатина
int sizeMeter; // размер на таблицата
// Избягвайте (x) в полза на горното
int ниво, размерMeter;
// Предпочитам () - Включете единица в име или тип променлива
дълга анкетаIntervalMs;
int fileSizeGb;
Сума  fileSize;
// Избягвайте (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
дълго време = 3000000000l;

Поставете декларации само в началото на блоковете (Блокът е код, заобиколен от къдрави скоби {и}). Не чакайте да декларирате променливи до първата им употреба; това може да обърка небрежния програмист и да попречи на преносимостта на кода в обхвата.

// Предпочитам () деклариране в началото на блока.
публична невалидност 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;
  • Отделете всички двоични оператори, с изключение на "." От операнди, използващи интервал
  • Отворената скоба „{” се появява в края на същия ред като декларацията или метода за деклариране, а затварящата скоба „}” започва ред сам по себе си отстъпен
// Предпочитан () - интервал след „докато“ и преди „(„
докато (вярно) {
  ...
}
// Избягвайте (x) - За разлика от горе няма място
докато (вярно) {
  ...
}
// Предпочитам () - Няма интервал между „doSomething“ и „(„
публична невалидност doSomething () {
  ...
}
// Избягвайте (x) - За разлика от горното пространство
публична невалидност doSomething () {
  ...
}
// Предпочитан () - Добавете интервал след аргумент
public void doSomething (int a, int b) {
  ...
}
// Предпочитан () - Пространство между операнд и оператори (т.е. +, =)
a + = c + d;
a = (a + b) / (c * d);
докато (d ++ = s ++) {
  п ++;
}

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

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

Има моменти, че коментарът към сложен фрагмент от код, метод, клас не добавя никаква стойност или служи на предназначението му. Това обикновено се случва, когато се коментира в името на него.

Коментарите трябва да се използват за преглед на кода и предоставяне на допълнителна информация, която не е лесно достъпна в самия код. Да започваме. Има два вида коментари

Коментари за изпълнение - имат за цел да коментират код или да коментират конкретна реализация на кода.

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

Честотата на коментарите понякога отразява лошото качество на кода. Когато се почувствате принудени да добавите коментар, помислете за пренаписването на кода, за да стане по-ясно.

Видове коментари за изпълнение

Има четири (4) вида коментари за изпълнение, както е показано по-долу

  • Блокиране на коментар - вижте примера по-долу
  • Коментар за един ред - когато коментарът не е по-дълъг от ред
  • Последни коментари - Много кратък коментар се премести в десния край
  • Коментар в края на реда - започва коментар, който продължава към новата линия. Той може да коментира пълен ред или само частичен ред. Той не трябва да се използва на последователни множество реда за коментари с текст; Въпреки това, той може да се използва в последователни няколко реда за коментиране на секции от код.
// Блокиране на коментар
/ *
 * Употреба: Предоставя описание на файлове, методи, структури от данни
 * и алгоритми. Може да се използва в началото на всеки файл и
 * преди всеки метод. Използва се за дълги коментари, които не отговарят на a
 * една линия. 1 Празна линия, за да продължите след коментара на блока.
 * /
// Единичен коментар
ако (условие) {
 / * Справете се със състоянието. * /
  ...
}
// Последен коментар
ако (a == 2) {
 връщане ИСТИНСКИ; /* специален случай */
} else {
 връщането еPrime (a); / * работи само за странно a * /
}
// Коментар в края на реда
ако (foo> 1) {
  // Направете двойно обръщане.
  ...
} else {
  върнете невярно; // Обяснете защо тук.
}
// ако (бар> 1) {
//
// // Направете троен флип.
// ...
//}
// останало
// връщане невярно;

Коментари към документацията (т.е. Javadoc)

Javadoc е инструмент, който генерира HTML документация от вашия Java код, използвайки коментарите, които започват с / ** и завършват с * / - вижте Wikipedia за повече подробности за това как работи Javadoc или просто четете заедно.

Ето пример за Javadoc

/ **
 * Връща обект на изображение, който след това може да бъде рисуван на екрана.
 * Аргументът за URL трябва да посочва абсолютен {@link URL}. Името
 * аргументът е спецификатор, който е относително към аргумента на url.
 * 

 * Този метод винаги се връща незабавно, независимо дали  * изображението съществува. Когато този аплет се опита да начертае изображението  * на екрана, данните ще бъдат заредени. Графичните примитиви  *, който рисува изображението, постепенно ще рисува върху екрана.  *  * @param url абсолютен URL адрес, даващ основното местоположение на изображението  * @param име местоположението на изображението, в сравнение с аргумента на url  * @ върнете изображението на посочения URL адрес  * @ Вижте изображението  * /  обществено изображение getImage (URL адрес, име на низ) {         опитвам {             върнете getImage (нов URL адрес (URL, име));         } улов (MalformedURLException e) {             връща нула;         }  }

И горното би довело до HTML, както следва, когато javadoc се изпълнява срещу кода, който има горното

Вижте тук за повече информация

Ето някои ключови маркери, които можете да използвате, за да подобрите качеството на генерираната java документация.

@author => @author Raf
@code => {@code A  C}
@deprecated => @depreposed deprecation-message
@exception => @exception IOException хвърлен, когато
@link => {@link package.class # член етикет}
@param => @param описание на параметър-име
@return => Какво се връща методът
@see => @see "string" ИЛИ @виж  
@since => За посочване на версията, когато се добави обществено достъпен метод

За пълен списък и по-подробно описание вижте тук

Стандартът за кодиране в Twitter съветва да не се използва маркер @author

Кодът може да сменя ръцете много пъти през живота си и доста често оригиналният автор на изходния файл е без значение след няколко повторения. Смятаме, че е по-добре да се доверим на историята на предаване и на собствениците на файлове, за да определим собствеността върху кода.

Следват примери за това как можете да напишете коментар за документация, който е проницателен, както е описано в стандарта за кодиране в Twitter

// Лошо.
// - Документът не казва нищо, че декларацията на метода не го направи.
// - Това е „документацията за пълнене“. Ще премине проверка на стила, но
не помага на никого
/ **
 * Разделя низа.
 *
 * @param s A низ.
 * @return Списък с низове.
 * /
Списък  split (String s);
// По-добре.
// - Знаем на какво се разделя методът.
// - Все пак някакво неопределено поведение.
/ **
 * Разделя низа на бялото пространство.
 *
 * @param s Низът за разделяне. {@Code null} низ се третира като празен низ.
 * @return Списък на частите на входа, обозначени с празно пространство.
 * /
Списък  split (String s);
// Страхотен.
// - Обхваща още един ръб на калъфа.
/ **
 * Разделя низа на бялото пространство. Повторни символи с бяло пространство
 * са сринати.
 *
 * @param s Низът за разделяне. {@Code null} низ се третира като празен низ.
 * @return Списък на частите на входа, обозначени с празно пространство.
 * /
Списък  split (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): Съобщение за действие описва какво трябва да се направи

Крайната игра е да напишете код, който улеснява живота на бъдещите автори и поддръжници.

Крайната игра

Други подходящи материали за четене

Списък на съответните статии, които са от значение за писане на код, чист, добре структуриран, лесен за четене и поддържане. Ако искате да прочетете повече, определено препоръчайте следното

и още един добър списък със съвети за писане на чист код