После некоторого программирования (например, почти 20 лет в моем случае время летит, когда вам весело), вы начинаете понимать эти привычки. Потому что, ты знаешь …
Вот почему люди используют «защитное программирование», то есть параноидальные привычки, которые иногда имеют полный смысл, а иногда являются довольно неясными и / или умными и, возможно, немного жуткими, когда вы думаете о человеке, который написал это. Вот мой личный список из 10 лучших, но параноидальных техник программирования Java. Поехали:
1. Поместите строковый литерал первым
Это просто плохая идея предотвратить случайное исключение NullPointerException
, поместив литерал String
в левую часть сравнения equals()
как таковое:
1
2
3
4
5
|
// Bad if (variable.equals( "literal" )) { ... } // Good if ( "literal" .equals(variable)) { ... } |
Это ежу понятно. Ничто не потеряно от перефразирования выражения от менее хорошей версии к лучшей. Если бы у нас были настоящие Варианты, правда? Разное обсуждение …
2. Не доверяйте ранним API JDK
В первые дни Java программирование, должно быть, было большой болью. API были все еще очень незрелыми, и вы, возможно, натолкнулись на фрагмент кода, подобный этому:
1
2
3
4
5
6
7
8
|
String[] files = file.list(); // Watch out if (files != null ) { for ( int i = 0 ; i < files.length; i++) { ... } } |
Выглядит параноиком? Возможно, но читайте Javadoc :
Если это абстрактное имя пути не обозначает каталог, тогда этот метод возвращает ноль. В противном случае возвращается массив строк, по одной для каждого файла или каталога в каталоге.
Да правильно. Лучше добавить еще один чек, чтобы быть уверенным:
01
02
03
04
05
06
07
08
09
10
|
if (file.isDirectory()) { String[] files = file.list(); // Watch out if (files != null ) { for ( int i = 0 ; i < files.length; i++) { ... } } } |
Облом! Нарушение правил № 5 и № 6 наших 10 тонких рекомендаций при написании кода Java . Так что будьте готовы и добавьте эту null
проверку!
3. Не верьте этому «-1»
Это параноик, я знаю. В Javadoc String.indexOf()
четко сказано, что…
возвращается индекс первого вхождения символа в последовательности символов, представленной этим объектом, или -1, если символ не встречается.
Значит, -1
можно считать само собой разумеющимся, верно? Я говорю нет. Учти это:
1
2
3
4
5
|
// Bad if (string.indexOf(character) != - 1 ) { ... } // Good if (string.indexOf(character) >= 0 ) { ... } |
Кто знает. Возможно, в какой-то момент времени им потребуется ДРУГОЕ кодирование, чтобы сказать, что otherString
содержалась бы, если бы проверялась без otherString
регистра… Возможно, хороший случай для возврата -2
? Кто знает.
В конце концов, у нас были миллиарды дискуссий об ошибке в миллиард долларов, которая равна NULL
. Почему бы нам не начать обсуждение -1
, что в некотором смысле является альтернативным null
для примитивного типа int
?
4. Избегайте случайного назначения
Ага. Это случается с лучшими (хотя, не со мной. См. # 7).
(Предположим, что это JavaScript, но давайте будем параноиком по поводу языка)
1
2
3
4
5
6
7
8
|
// Ooops if (variable = 5 ) { ... } // Better (because causes an error) if ( 5 = variable) { ... } // Intent (remember. Paranoid JavaScript: ===) if ( 5 === variable) { ... } |
Еще раз. Если в вашем выражении есть литерал, поместите его слева. Вы не можете случайно ошибиться, если хотите добавить еще один знак =
.
5. Проверьте на ноль И длину
Всякий раз, когда у вас есть коллекция, массив и т. Д., Убедитесь, что она присутствует и не пуста.
1
2
3
4
5
|
// Bad if (array.length > 0 ) { ... } // Good if (array != null && array.length > 0 ) { ... } |
Вы никогда не знаете, откуда взялись эти массивы. Возможно из раннего JDK API?
6. Все методы являются окончательными
Вы можете сказать мне все, что вы хотите о ваших принципах открытого / закрытого, это все бред. Я не доверяю вам (чтобы правильно продлить мои занятия), и я не доверяю себе (чтобы не случайно продлить мои занятия). Вот почему все, что явно не предназначено для подтипирования (то есть только интерфейсы), строго final
. См. Также пункт № 9 из нашего списка 10 тонких рекомендаций при кодировании Java .
1
2
3
4
5
|
// Bad public void boom() { ... } // Good. Don't touch. public final void dontTouch() { ... } |
Да. Это окончательно. Если это не работает для вас, исправьте его, или установите его, или перепишите байт-код. Или отправьте запрос функции. Я уверен, что ваше намерение отвергнуть вышесказанное в любом случае не очень хорошая идея.
7. Все переменные и параметры являются окончательными
Как я сказал. Я не доверяю себе (чтобы случайно не перезаписать мои ценности). Сказав это, я не доверяю себе вообще. Потому как…
… Поэтому все переменные и параметры также становятся final
.
01
02
03
04
05
06
07
08
09
10
11
|
// Bad void input(String importantMessage) { String answer = "..." ; answer = importantMessage = "LOL accident" ; } // Good final void input( final String importantMessage) { final String answer = "..." ; } |
Хорошо, я признаю На этот раз я не часто обращаюсь, правда, хотя должен. Хотелось бы, чтобы в Java все было правильно, как в Scala , где люди просто набирают val
везде, даже не задумываясь об изменчивости — за исключением случаев, когда они нуждаются в этом явно (редко!) Через var
.
8. Не доверяйте дженерикам при перегрузке
Да. Это может случится. Вы верите, что написали этот супер приятный API, который просто потрясающий и полностью интуитивный, и вместе с ним появляется пользователь, который просто вводит все до Object
до тех пор, пока проклятый компилятор не перестанет ругаться, и вдруг они сошлются на неправильный метод, думая, что это ваш вина (это всегда так).
Учти это:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
// Bad <T> void bad(T value) { bad(Collections.singletonList(value)); } <T> void bad(List<T> values) { ... } // Good final <T> void good( final T value) { if (value instanceof List) good((List<?>) value); else good(Collections.singletonList(value)); } final <T> void good( final List<T> values) { ... } |
Потому что, вы знаете … Ваши пользователи, они как
1
2
3
4
|
// This library sucks @SuppressWarnings ( "all" ) Object t = (Object) (List) Arrays.asList( "abc" ); bad(t); |
Доверьтесь мне. Я видел все. Включая такие вещи, как
Хорошо быть параноиком.
9. Всегда бросайте на переключатель по умолчанию
Переключатель … Одно из тех забавных утверждений, где я не знаю, окаменеть ли от страха или просто плакать. Во всяком случае, мы застряли с switch
, поэтому мы можем сделать это правильно, когда нам нужно. Т.е.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
// Bad switch (value) { case 1 : foo(); break ; case 2 : bar(); break ; } // Good switch (value) { case 1 : foo(); break ; case 2 : bar(); break ; default : throw new ThreadDeath( "That'll teach them" ); } |
Потому что в тот момент, когда value == 3
введено в программное обеспечение, оно обязательно придет! И не говорите enum
, потому что это произойдет и с enums
!
10. Переключить с помощью фигурных скобок
На самом деле, switch
— самое злое утверждение, которое когда-либо было разрешено любому человеку, когда он был пьян или проиграл пари. Рассмотрим следующий пример:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
// Bad, doesn't compile switch (value) { case 1 : int j = 1 ; break ; case 2 : int j = 2 ; break ; } // Good switch (value) { case 1 : { final int j = 1 ; break ; } case 2 : { final int j = 2 ; break ; } // Remember: default : throw new ThreadDeath( "That'll teach them" ); } |
Внутри оператора switch
существует только одна область видимости, определенная среди всех операторов case
. На самом деле, эти операторы case
даже не являются операторами, они похожи на метки, а switch
— это вызов goto. Фактически, вы даже можете сравнить операторы case
с удивительным оператором FORTRAN 77 ENTRY , устройством, тайна которого превосходит только его мощь.
Это означает, что переменная final int j
определена для всех различных случаев, независимо от того, выполним ли мы break
или нет. Не очень интуитивно понятно. Вот почему всегда полезно создать новый вложенный контекст для каждого case
помощью простого блока . (но не забывайте break
в блоке!)
Вывод
Параноидальное программирование иногда может показаться странным, так как код часто оказывается более многословным, чем действительно необходимо. Вы можете подумать: «О, этого никогда не случится», но, как я уже сказал. Приблизительно после 20 лет программирования вы просто не хотите больше исправлять эти глупые маленькие ненужные ошибки, которые существуют только потому, что язык настолько стар и несовершенен. Потому что ты знаешь …
Теперь твоя очередь!
Какой твой самый параноидальный изюминка в программировании?
Ссылка: | Топ-10 полезных и в то же время параноидальных технологий Java-программирования от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и JOOQ . |