Анимация
JavaScript
|
Главная Библионтека 48. Избегайте ненужных идентификаторов Имена для констант часто вообще не нужны. Например, не определяйте значения, возвращаемые при ошибке; если возвращается всего одна ошибка, возвратите просто FALSE. Не делайте так: enum { INSERT ERROR, DELETE ERROR }; insert() return INSERT ERROR; delete() return DELETE ERROR; а просто возвратите 0 в случае ошибки и в случае успеха любое правильное значение типа 1. 49. Именованные константы для булевых величин редко необходимы Выбор неверного имени может добавить значительную ненужную сложность в вашу программу. Рассмотрим следующую простейшую функцию, которая подсчитывает количество слов в строке: int nwords( const char *str) typedef enum { IN WORD, BETWEEN WORDS } wstate; int word count = 0; wstate state = BETWEEN WORDS; for(; *str ; ++str ) if( isspace(*str) ) state = BETWEEN WORDS; else if( state != IN WORD ) ++word count; state = IN WORD; return word count; Неправильно выбранное имя state заставило нас ввести два ненужных * В стандарте ISO/IEC 14882 существует тип bool. Имеет смысл заменить тип переменной is left child на bool. - Ред. идентификатора: IN WORD и BETWEEN WORDS. Теперь взгляните на этот вариант: int nwords2( const char *str) { int word count = 0; int in word = 0; for(; *str ; ++str ) if( isspace(*str) ) in word = 0; else if ( !in word ) ++word count; in word = 1; return word count; Переименование нечетко названной переменной state во что-нибудь, что действительно описывает назначение переменной, позволило мне исключить булевые именованные константы IN WORD и BETWEEN WORDS. Получившаяся подпрограмма меньше и легче читается. Вот другой пример. Следующая программа: enum child type { I AM A LEFT CHILD, I AM A RIGHT CHILD }; struct tnode child type position; struct tnode *left, *right; t.position = I AM LEFT CHILD; if( t.position == I AM LEFT CHILD ) может быть упрощена подобным образом*: struct tnode unsigned is left child ; struct tnode *left, *right; t.is left child = 1; if( t.is left child ) ... тем самым исключая два ненужных идентификатора. И вот последний пример: enum { SOME BEHAVIOR, SOME OTHER BEHAVIOR, SOME THIRD BEHAVIOR }; f( SOME BEHAVIOR, x); f( SOME OTHER BEHAVIOR, x); f( SOME THIRD BEHAVIOR, x); требующий четырех идентификаторов (три именованные константы и имя функции). Лучше, хотя это не всегда возможно, исключить селекторную константу в пользу дополнительных функций: some behavior(x); some other behavior(x); some third behavior(x); Обратной стороной этой монеты является вызов функции. Рассмотрим следующий прототип: create window( int has border, int is scrollable, int is maximized ); Я снова выбрал рациональные имена для исключения необходимости в именованных константах. К сожалению, вызов этой функции плохо читаем: create window( TRUE, FALSE, TRUE ); Просто взглянув на такой вызов, я не получу никакого представления о том, как будет выглядеть это окно. Несколько именованных констант проясняют обстоятельства в этом вызове: enum { UNBORDERED =0; BORDERED =l}; Нужно показать значения, enum { UNSCROLLABLE=0; SCROLLABLE =1}; или create window() enum { NORMAL SIZE =0; MAXIMIZED =l}; не будет работать. ... create window( BORDERED, UNSCROLLABLE, MAXIMIZED ); но теперь у меня другая проблема. Я не хочу использовать именованные константы внутри самой create window() . Они здесь только для того, чтобы сделать ее вызов более читаемым, и я не хочу загромождать эту функцию таким кодом, как: if( has border == BORDERED ) ... сравнивая его с более простым: if ( has border ) ... 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [ 17 ] 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |