Эта страница содержит наиболее типичные ошибки, которые я вижу в коде Java людей, работающих со мной. Статический анализ (мы используем qulice, не можем поймать все ошибки по понятным причинам, и поэтому я решил перечислить их все здесь.
Дайте мне знать, если вы хотите увидеть что-то еще, добавленное здесь, и я буду рад вам помочь
Все перечисленные ошибки относятся к объектно-ориентированному программированию в целом и к Java в частности.
Имена классов
Прочитайте этот короткий «Что такое объект?» статья. Ваш класс должен быть абстракцией реальной сущности без «валидаторов», «контроллеров», «менеджеров» и т. Д. Если имя вашего класса заканчивается на «-er» — это плохой дизайн .
И, конечно, служебные классы являются анти-шаблонами, такими как StringUtils , FileUtils и IOUtils от Apache. Выше приведены прекрасные примеры ужасных замыслов. Прочитайте этот пост: OOP Альтернатива служебным классам .
Конечно, никогда не добавляйте суффиксы или префиксы, чтобы различать интерфейсы и классы . Например, все эти имена ужасно неправильны: IRecord , IfaceEmployee или RecordInterface . Обычно имя интерфейса — это имя реальной сущности, а имя класса должно объяснять детали его реализации. Если ничего не скажешь о реализации, назовите ее Default, Simple или что-то подобное. Например:
|
1
2
3
4
|
class SimpleUser implements User {};class DefaultRecord implements Record {};class Suffixed implements Name {};class Validated implements Content {}; |
Имена методов
Методы могут либо возвращать что-то, либо возвращать void . Если метод возвращает что-то, его имя должно объяснять, например, что он возвращает (никогда не используйте префикс get ):
|
1
2
3
|
boolean isValid(String name);String content();int ageOf(File file); |
Если он возвращает void, то его имя должно объяснять, что он делает . Например:
|
1
2
3
|
void save(File file);void process(Work work);void append(File file, String line); |
Существует только одно исключение из только что упомянутого правила — методы тестирования для JUnit. Они объяснены ниже.
Имена методов испытаний
Имена методов в тестах JUnit должны создаваться как английские предложения без пробелов. Это проще объяснить на примере:
|
1
2
3
4
5
6
|
/** * HttpRequest can return its content in Unicode. * @throws Exception If test fails */public void returnsItsContentInUnicode() throws Exception {} |
Важно, чтобы первое предложение вашего JavaDoc начиналось с названия класса, который вы тестируете, а затем с помощью can . Итак, ваше первое предложение всегда должно быть похоже на «кто-то может что-то сделать».
Имя метода будет точно таким же, но без субъекта. Если я добавлю тему в начале имени метода, я получу полное английское предложение, как в примере выше: «HttpRequest возвращает свое содержимое в юникоде».
Обратите внимание, что тестовый метод не начинается с can Только комментарии JavaDoc начинаются с can. Кроме того, имена методов не должны начинаться с глагола.
Рекомендуется всегда объявлять методы тестирования как Exception .
Имена переменных
Избегайте составных имен переменных, таких как timeOfDay , firstItem или httpRequest . Я имею в виду как переменные класса, так и переменные внутри метода. Имя переменной должно быть достаточно длинным, чтобы избежать двусмысленности в его видимости, но не слишком длинным, если это возможно. Имя должно быть существительным в единственном или множественном числе или соответствующей аббревиатурой. Например:
|
1
2
3
4
|
List<String> names;void sendThroughProxy(File file, Protocol proto);private File content;public HttpRequest request; |
Иногда могут возникнуть коллизии между параметрами конструктора и свойствами класса, если конструктор сохраняет входящие данные в созданном объекте. В этом случае я рекомендую создавать сокращения, удаляя гласные (посмотрите, как USPS сокращает названия улиц ).
Другой пример:
|
1
2
3
4
5
6
|
public class Message { private String recipient; public Message(String rcpt) { this.recipient = rcpt; }} |
Во многих случаях лучший совет для имени переменной можно определить, прочитав ее имя класса. Просто напишите это маленьким письмом, и вам должно быть хорошо:
|
1
2
3
|
File file;User user;Branch branch; |
Однако никогда не делайте то же самое для примитивных типов, таких как Integer number или String string .
Вы также можете использовать прилагательное, когда есть несколько переменных с разными характеристиками. Например:
|
1
|
String contact(String left, String right); |
Конструкторы
Без исключений, должен быть только один конструктор, который хранит данные в переменных объекта. Все остальные конструкторы должны вызывать его с другими аргументами. Например:
|
1
2
3
4
5
6
7
8
9
|
public class Server { private String address; public Server(String uri) { this.address = uri; } public Server(URI uri) { this(uri.toString()); }} |
Одноразовые переменные
Избегайте одноразовых переменных любой ценой. Под «одноразовыми» я подразумеваю переменные, которые используются только один раз. Как в этом примере:
|
1
2
|
String name = "data.txt";return new File(name); |
Эта переменная используется только один раз, и код должен быть изменен на:
|
1
|
return new File("data.txt"); |
Иногда в очень редких случаях — в основном из-за лучшего форматирования — могут использоваться одноразовые переменные. Тем не менее, старайтесь избегать таких ситуаций любой ценой.
Исключения
Излишне говорить, что вы никогда не должны глотать исключения, а просто позволять им пузыриться как можно выше. Частные методы всегда должны позволять проверенным исключениям выходить.
Никогда не используйте исключения для управления потоком. Например, этот код неверен:
|
1
2
3
4
5
6
|
int size;try { size = this.fileSize();} catch (IOException ex) { size = 0;} |
Серьезно, что, если это IOException говорит «диск заполнен»? Будете ли вы по-прежнему считать, что размер файла равен нулю, и двигаться дальше?
вдавливание
Для отступа главное правило состоит в том, что скобка должна либо заканчивать линию, либо быть закрытой на той же самой строке (обратное правило применяется к закрывающей скобке). Например, следующее неверно, поскольку первая скобка не закрыта на одной строке и после нее есть символы. Вторая скобка также в беде, потому что перед ней есть символы, и она не открыта в той же строке:
|
1
2
|
final File file = new File(directory, "file.txt"); |
Правильный отступ должен выглядеть так:
|
01
02
03
04
05
06
07
08
09
10
|
StringUtils.join( Arrays.asList( "first line", "second line", StringUtils.join( Arrays.asList("a", "b") ) ), "separator"); |
Второе важное правило отступов гласит, что вы должны поместить как можно больше в одну строку — в пределах 80 символов. Приведенный выше пример недопустим, поскольку его можно сжать:
|
1
2
3
4
5
6
7
|
StringUtils.join( Arrays.asList( "first line", "second line", StringUtils.join(Arrays.asList("a", "b")) ), "separator"); |
Избыточные Константы
Константы класса следует использовать, когда вы хотите обмениваться информацией между методами класса, и эта информация является характеристикой (!) Вашего класса. Не используйте константы в качестве замены строковых или числовых литералов — очень плохая практика, которая приводит к загрязнению кода. Константы (как и любой объект в ООП) должны иметь значение в реальном мире. Какое значение имеют эти константы в реальном мире:
|
1
2
3
4
|
class Document { private static final String D_LETTER = "D"; // bad practice private static final String EXTENSION = ".doc"; // good practice} |
Другой типичной ошибкой является использование констант в модульных тестах, чтобы избежать дублирования строковых / числовых литералов в тестовых методах. Не делай этого! Каждый метод тестирования должен работать со своим набором входных значений.
Используйте новые тексты и цифры в каждом новом методе испытаний. Они независимы. Итак, почему они должны использовать одни и те же входные константы?
Тестирование связи данных
Это пример связи данных в тестовом методе:
|
1
2
3
|
User user = new User("Jeff");// maybe some other code hereMatcherAssert.assertThat(user.name(), Matchers.equalTo("Jeff")); |
В последней строке мы связываем "Jeff" с тем же строковым литералом из первой строки. Если спустя несколько месяцев кто-то захочет изменить значение в третьей строке, ему / ей придется потратить дополнительное время на поиск, где еще "Jeff" используется в том же методе.
Чтобы избежать этой связи данных, вы должны ввести переменную.
Похожие сообщения
Вы также можете найти эти сообщения интересными:
- Почему NULL это плохо?
- Объекты должны быть неизменными
- ООП Альтернатива служебным классам
- Избегайте конкатенации строк
- Простой Java SSH клиент
| Ссылка: | Типичные ошибки в Java-коде от нашего партнера по JCG Егора Бугаенко в блоге About Programming . |