Программирование >>  Решение нетривиальных задач 

1 ... 17 18 19 [ 20 ] 21 22 23 ... 77


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. Функция должна вызываться более одного раза,

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

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



1 ... 17 18 19 [ 20 ] 21 22 23 ... 77

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика