|
Программирование >> Решение нетривиальных задач
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. Функция должна вызываться более одного раза, Кроме того, если функция должным образом связана (т.е. если она выполняет единственную операцию и весь код функции работает на ее результат), то нет причины извлекать кусок кода в другие функции, если только вы не желаете использовать эту часть кода где-то еще. Мой опыт говорит, что когда функция становится слишком большой, то часто возможно выделить куски, которые обладают достаточной общностью, чтобы быть использованными где-либо еще в программе, так что это правило на самом деле не противоречит правилу маленькое - прекрасно . Если вы не выделяете этот код, то блочный комментарий, описывающий назначение этого блока программы, который вы могли бы выделить, служит той же самой цели, что и имя функции - документированию. Тем не менее, иногда выделение кода в функции меньшего размера существенно улучшает читаемость этого кода по причине устранения беспорядка. Однако эта практика - создание абстракции для части кода в виде имени функции - добавляет идентификаторы в область глобальных
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |