Анимация
JavaScript


Главная  Библионтека 

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

printf("%s", str ? str : "<пусто>");

гораздо элегантнее, чем: if ( str == NULL )

printf( "<пусто>" );

else

printf( "%s", str );

Вы к тому же экономите на двух вызовах printf() . Мне также часто приходится видеть неправильное использование операций ++ и --. Весь смысл автоинкремента или автодекремента заключается в соединении этих операций с другими. Вместо:

while (*p)

putchar ( *p ); ++p;

или:

for (;*p;++p ) putchar ( *p );

используйте:

while(*p)

putchar ( *p++ );

Этот код вполне читаем для компетентного программиста на языке Си, даже если ему нет эквивалентной операции в ФОРТРАНе или Паскале.

Вы также никогда не должны прятать операторы в макросах из-за того, что вам просто не нравится, как они выглядят. Я однажды видел следующее в реальной программе:

struct tree node

struct tree node *lftchld;

#define left child(x) ((x)->lftchld)

...

traverse( tree node *root )

if( left child(root) )

traverse( left child( root ) ); ...

Программист намеренно сделал определение структуры труднее читаемым для того, чтобы избежать конфликта имен между полем и совершенно необходимым макросом, и все из-за того, что ему не нравился



внешний вид оператора ->. Для него было бы гораздо лучшим выходом просто назвать поле left child и совсем избавиться от макроса.

Если вы действительно думаете, что программа должна внешне выглядеть как на Паскале, чтобы быть читаемой, то вы должны программировать на Паскале, а не на Си или Си++.

51. Функция должна делать только одно дело

Это обычно не очень удачная мысль - записывать то, что должна делать функция, через ее аргументы. Это должно делать имя функции. Например:

UpdateAllViews( CView *sender, long lhint, CObject *phint )

sender lhint phint

NULL xx xx Начальное обновление, вызываемое из обрамляющего окна

Cview* 0 Crect* Вызывается, когда встроенный объект становится действительным. phint

указывает на прямоугольник документа,

сохраняя положение недействительного

объекта

Cview* 1 Crect* Сообщение, посылаемое объектом CView* ("sender" - передатчик). phint сохраняет

для CView* обрамляющее окно его клиента.

Вам нужны вместо этого три функции: initial update() , update embedded object() и update view(). Верным ключом для понимания того, что здесь что-то не так, является туманная природа имен аргументов. Функциям не должны передаваться "намеки". Им должны даваться указания.

52. Иметь слишком много уровней абстракции или инкапсуляции так же плохо, как и слишком мало

Основной смысл использования таких абстракций, как функции или символьные константы (или инкапсуляций, подобных определениям struct или class), заключается в улучшении читаемости программ. Не пользуйтесь ими просто потому, что вы можете делать это. Например, вложенные структуры в данном фрагменте не служат какой-либо полезной цели:

struct tree node; struct child ptr

unsigned is thread;



struct tree node *child;

struct tree node

struct child ptr left, right;

tree node *p;

if( !p->left.am a thread ) p = p->left.child;

Следующий код лучше читается, потому что в нем меньше точек, и легче сопровождается, так как в нем нужно отлаживать на одно определение меньше:

struct tree node

struct tree node *left child; unsigned left is thread : 1;

struct tree node *right child; unsigned right is thread : 1;

if( !p->left is thread ) p = p->left child;

53. Функция должна вызываться более одного раза,

Кроме того, если функция должным образом связана (т.е. если она выполняет единственную операцию и весь код функции работает на ее результат), то нет причины извлекать кусок кода в другие функции, если только вы не желаете использовать эту часть кода где-то еще. Мой опыт говорит, что когда функция становится слишком большой, то часто возможно выделить куски, которые обладают достаточной общностью, чтобы быть использованными где-либо еще в программе, так что это правило на самом деле не противоречит правилу "маленькое - прекрасно". Если вы не выделяете этот код, то блочный комментарий, описывающий назначение этого блока программы, который вы могли бы выделить, служит той же самой цели, что и имя функции - документированию.

Тем не менее, иногда выделение кода в функции меньшего размера существенно улучшает читаемость этого кода по причине устранения беспорядка. Однако эта практика - создание абстракции для части кода в виде имени функции - добавляет идентификаторы в область глобальных имен, и эта возросшая общая сложность является определенным минусом.



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