Совершенный код. Совершенный код. Мастер-класс. Стив Макконнелл. Руководство по стилю программирования и конструированию по
Скачать 5.88 Mb.
|
ГЛАВА 34 Основы мастерства 829 Если вы ловите себя на том, что работаете над повторяющимся кодом или вноси# те похожие изменения в несколько фрагментов, вам следует почувствовать себя «неловко и неприятно», усомнившись в том, что управление было адекватно цен# трализовано в классах или методах. Если из#за проблем с отдельным классом вы не можете с легкостью создать тестовые леса, вы должны почувствовать сомне# ние и спросить себя, не слишком ли сильно класс сопряжен с другими классами. Если вы не можете повторно использовать код в других программах, потому что некоторые классы слишком взаимозависимы, это также предупреждает о черес# чур сильном сопряжении классов. Погрузившись в детали программы, обращайте внимание на предупреждающие знаки, указывающие на то, что часть проекта программы недостаточно хорошо определена для кодирования. Трудности при написании комментариев, именова# нии переменных и декомпозиции проблемы на связные классы с ясными интер# фейсами — все это говорит о том, что нужно более тщательно выполнить проек# тирование перед началом кодирования. Невыразительные имена и сложности при описании фрагментов кода лаконичными комментариями — другие признаки проблем. Если вы хорошо представляете проект программы, реализовать низко# уровневые детали будет легко. Обращайте внимание на признаки того, что программу трудно понять. Об этом свидетельствуют любые неудобства. Если это трудно для вас, для будущих програм# мистов это окажется еще труднее. Они по достоинству оценят ваши дополнитель# ные усилия по улучшению кода. Если вы разгадываете код, а не читаете его, он слишком сложен. Если он сложен, он неверен. Сделайте его проще. Если вы хотите воспользоваться всеми преимуществами предупреждаю# щих знаков, программируйте так, чтобы создать собственные предупреж# дения. Это полезно потому, что, даже если вам известны предупреждаю# щие знаки, их на удивление легко упустить из виду. Гленфорд Майерс исследовал исправления дефектов и обнаружил, что самой частой причиной плохого обна# ружения ошибок была простая невнимательность. Ошибки были видны в резуль# татах тестов, но программисты их не замечали (Myers, 1978b). Программируйте так, чтобы ошибки было трудно не заметить. Примером этого может служить установка указателей в NULL после их освобождения, чтобы их ошибочное использование вызывало безобразные проблемы. Освобожденный указатель даже после освобождения может указывать на корректную область па# мяти. Установка указателя в NULL гарантирует, что он будет указывать на некор# ректный адрес, благодаря чему ошибку будет сложнее не заметить. Предупреждения компилятора являются буквальными предупреждающими знаками, которые часто упускают из виду. Если ваша программа генерирует предупрежде# ния или ошибки, устраните их. Невелика вероятность того, что вы заметите тон# кие предупреждающие знаки, если вы игнорируете те, на которых прямо написа# но «ПРЕДУПРЕЖДЕНИЕ». Почему внимание к интеллектуальным предупреждающим знакам особенно важ# но при разработке ПО? Качество мышления, воплощаемое в программе, во мно# гом определяет качество самой программы, поэтому внимание к предупреждениям о качестве мышления напрямую влияет на итоговый продукт. 830 ЧАСТЬ VII Мастерство программирования 34.8. Итерируйте, итерируйте и итерируйте Итерация полезна на многих этапах разработки ПО. При разработке первоначаль# ной спецификации системы вы составляете с заказчиком несколько версий тре# бований, пока не достигнете согласия. Это итеративный процесс. Гибкий процесс разработки, предусматривающий создание и поставку системы по частям, тоже итеративен. Прототипирование, имеющее целью быструю и дешевую разработку предварительных вариантов решений, — еще одна форма итерации. Итеративная выработка требований, наверное, не менее важна, чем любой другой аспект про# цесса разработки ПО. Проекты завершаются неудачей потому, что разработчики приступают к решению проблемы, не изучив альтернативных вариантов. Итера# ция позволяет лучше узнать систему перед ее созданием. Оценки сроков при первоначальном планировании проекта могут сильно разли# чаться в зависимости от используемой методики оценки (см. главу 28). Итеративный подход дает более точную оценку, чем единственная методика. Проектирование ПО — процесс эвристический и, как все эвристические процес# сы, допускает итеративные ревизии и улучшения. Правильность ПО обычно про# веряется, а не доказывается, а значит, оно тестируется и разрабатывается итеративно, пока на все вопросы не будут получены правильные ответы. И высокоуровневые, и низкоуровневые попытки проектирования следует повторять. Первая попытка мо# жет привести к работоспособному решению, но едва ли оно окажется наилучшим. Неоднократное применение разных подходов позволяет узнать о проблеме много такого, что ускользает при использовании единственного подхода. Идея итерации снова вступает в игру при оптимизации кода. Как только ПО до# ведено до работоспособного состояния, вы можете переписать небольшие фраг# менты кода и добиться значительного повышения общей производительности системы. Однако многие попытки оптимизации ухудшают, а не улучшают код. Это неинтуитивный процесс, и некоторые методики, которые будто должны сделать систему более компактной и быстрой, на самом деле увеличивают ее и замедля# ют. Неопределенность результатов любого вида оптимизации заставляет пробо# вать один вид, оценивать быстродействие и пробовать другой. Если от устране# ния узкого места зависит достижение нужной производительности, вы можете оптимизировать код несколько раз, и более поздние попытки могут оказаться успешнее первой. Весь процесс разработки охвачен обзорами, что встраивает итерацию в любой этап, на котором они проводятся. Цель обзора — проверка качества работы, вы# полненной на данный момент. Если система не проходит обзора, она возвраща# ется на переработку. Если обзор проходит успешно, дальнейшая итерация не нужна. Говорят, инженерное дело — это умение сделать за 10 центов то, что любой мо# жет сделать за доллар. Итерация на более поздних этапах — это трата двух долла# ров на то, что любой может сделать за один. Фред Брукс советует «планировать выбросить один вариант программы, потому что это придется сделать в любом случае» (Brooks, 1995). Хитрость разработки ПО в том, чтобы создавать выбрасы# ваемые части как можно быстрее и дешевле — это и есть суть итерации на ран# них этапах разработки. ГЛАВА 34 Основы мастерства 831 34.9. И да отделена будет религия от разработки ПО Религия проявляется в разработке ПО по#разному: как догматичное следование единственной методике проектирования, как непоколебимая убежденность в пре# восходстве отдельного стиля форматирования или комментирования или как рьяный отказ от глобальных данных. Как бы то ни было, это всегда неуместно. Оракулы программирования Увы, догматиками бывают и некоторые из наиболее уважа# емых людей в нашей отрасли. Конечно, инновационные методики нужно разглашать, чтобы их могли попробовать практикующие разработчики. До того как эффективность методик можно будет полностью доказать или опровергнуть, их нужно испытать. Распространение результатов исследо# ваний на практикующих специалистов называется «передачей технологий» и иг# рает важную роль в совершенствовании способов разработки ПО. Однако распро# странение новой методологии нужно отличать от продажи чудодейственного средства от всех болезней программирования. Передача технологий — это совсем не то, чем занимаются торговцы догматичными методологиями, пытающиеся убедить вас в том, что их высокотехнологичная новинка решит все проблемы всех программистов во Вселенной. Забудьте обо всем, что вы изучили, потому что эта великолепная новая методика повысит производительность вашего труда в два раза во всех областях! Вместо чрезмерного увлечения модными штучками используйте смесь методик. Экспериментируйте с интересными новыми методиками, но делайте ставку на старые и надежные. Эклектизм Слепая вера в одну методику подавляет возможность выбо# ра, нужную для обнаружения наиболее эффективных реше# ний проблем. Будь разработка ПО детерминированным ал# горитмическим процессом, вы могли бы следовать жесткой методологии. Однако разработка ПО — не детерминирован# ный, а эвристический процесс, а значит, жесткие подходы редко приводят к успеху. Например, при проектировании иногда хорошо работает нисходящая декомпозиция, но иногда лучшим вариантом будет объектно#ориентированный подход, восходящая композиция или подход, основанный на структурах данных. Вы должны быть готовы к испытанию нескольких подходов, зная, что некоторые окажутся неэф# фективными, а какие#то приведут к успеху, но не зная заранее, какие из них ка# кие. Вам следует быть эклектичным. Приверженность одной методике вредна и тем, что она заставляет подгонять проблему под решение. Выбирая методику решения до полного понимания про# блемы, вы слишком спешите. Чрезмерное ограничение набора возможных реше# ний может исключить из области видимости наиболее эффективное решение. Перекрестная ссылка О том, как руководителям следует подхо- дить к религии программирова- ния, см. подраздел «Вопросы религии» раздела 28.5. Перекрестная ссылка О разли- чии между алгоритмическим и эвристическим подходами см. раздел 2.2, об эклектизме при проектировании — подраздел «Используйте итерацию» разде- ла 5.4. 832 ЧАСТЬ VII Мастерство программирования Любая новая методология поначалу вызывает дискомфорт, и совет избегать ре# лигии в программировании не подразумевает, что от новой методики следует отказаться при возникновении небольшой проблемы. Пересмотрите новую мето# дику, но не забывайте пересматривать и старые методики. С позиций эклектизма полезно подходить и к методикам, описанным в этой книге, и к методикам, рассматриваемым в других источниках. Некоторые подходы, представленные мной, имеют улучшенные альтернативы, и вы не можете ис# пользовать их одновременно. Вы должны выбрать для конк# ретной проблемы один или другой подход. Рассматривайте методики как инструменты и выбирайте наиболее подходящую для работы. В боль# шинстве случаев выбор инструмента не играет особой роли. Вы можете использо# вать торцовый ключ, плоскогубцы или разводной ключ. Однако иногда выбор очень важен, поэтому вам следует всегда делать выбор со всей тщательностью. Разработ# ка предполагает нахождение компромисса между конкурирующими методиками. Вы не сможете достичь компромисса, если преждевременно ограничите выбор един# ственным инструментом. Метафора инструментария полезна потому, что она делает абстрактную идею эклектизма конкретной. Если бы вы строили дом и ваш приятель Симпл Саймон всегда работал только плоскогубцами, отказываясь от торцового или разводного ключей, вы, вероятно, подумали бы, что он ведет себя странно, потому что не использует все инструменты, имеющиеся в его распоряжении. То же верно и при разработке ПО. На высоком уровне у вас есть альтернативные методики проекти# рования. На более детальном уровне вы можете выбрать для представления кон# кретной сущности один из нескольких типов данных. На еще более детальном уровне вы можете выбирать схемы форматирования и комментирования кода, именования переменных, определения интерфейсов классов и передачи парамет# ров в методы. Догматизм конфликтует с эклектичным подбором инструментов к конструиро# ванию ПО. Она несовместима с психологической установкой, необходимой для создания высококачественных программ. Экспериментирование Эклектизм тесно связан с экспериментированием. Вам нужно экспериментиро# вать на всем протяжении процесса разработки, но непреклонность подавляет этот импульс. Чтобы экспериментирование было эффективным, вы должны охотно изменять свои убеждения на основе результатов экспериментов — иначе экспе# риментирование становится пустой тратой времени. Многие негибкие подходы к разработке ПО основаны на страхе допустить ошибку, но нет ошибки серьезнее, чем глобальное стремление избежать ошибок. Проек# тирование — это процесс тщательного планирования мелких ошибок с целью предотвращения крупных. Экспериментирование при разработке ПО позволяет узнать, эффективен ли тот или иной подход, — сам эксперимент является успе# хом, если он решает проблему. Перекрестная ссылка О метафо- ре инструментария см. подраз- дел «Применение методов раз- работки ПО: интеллектуальный инструментарий» раздела 2.3. ГЛАВА 34 Основы мастерства 833 Экспериментирование уместно на стольких же уровнях, что и эклектизм. На каж# дом уровне, предоставляющем возможность эклектичного выбора, вы, вероятно, можете провести соответствующий эксперимент для определения оптимального подхода. На уровне разработки архитектуры эксперимент может заключаться в проектировании архитектуры ПО с использованием трех разных подходов. На уровне детального проектирования эксперимент может состоять в детализа# ции высокоуровневой архитектуры с использованием трех разных подходов к низ# коуровневому проектированию. На уровне языка программирования эксперимен# том может быть написание небольшой экспериментальной программы для изу# чения плохо знакомых вам аспектов языка. Эксперимент может заключаться в оптимизации фрагмента кода и оценке того, действительно ли он стал меньше или быстрее. На уровне общего процесса разработки ПО эксперимент может за# ключаться в сборе данных о качестве и производительности труда, отвечающих на вопрос, действительно ли инспекции позволяют обнаружить больше ошибок, чем анализ кода. Суть сказанного в том, что вы должны быть восприимчивы ко всем аспектам раз# работки ПО. Вы должны разобраться и в используемом процессе разработки, и в создаваемой системе. Непредвзятое экспериментирование и религиозное следо# вание предопределенному подходу исключают друг друга. Ключевые моменты Главная цель программирования — управление сложностью. Процесс программирования оказывает большое влияние на итоговый продукт. Групповое программирование является в большей степени общением с други# ми людьми, а не с компьютером. Индивидуальное программирование — это в первую очередь общение с самим собой, а не с компьютером. При неадекватном использовании конвенция программирования может ока# заться лекарством, причиняющим больше вреда, чем болезнь; при грамотном — конвенция добавляет ценную структуру в среду разработки, помогает управ# лять сложностью и облегчает общение. Программирование в терминах проблемы, а не решения помогает управлять сложностью. Внимание к интеллектуальным предупреждающим знакам вроде сомнения особенно важно в программировании, потому что программирование — по# чти исключительно умственная деятельность. Чем больше внимания итерации вы уделяете на конкретном этапе разработ# ки, тем лучше будет результат этого этапа. Догматичные методологии и разработка высококачественного ПО исключают друг друга. Заполняйте свой интеллектуальный инструментарий альтернатив# ными подходами к программированию и улучшайте навык выбора инструмента, лучше всего подходящего для работы. 834 ЧАСТЬ VII Мастерство программирования Г Л А В А 3 5 Где искать дополнительную информацию Содержание 35.1. Информация о конструировании ПО 35.2. Не связанные с конструированием темы 35.3. Периодические издания 35.4. Список литературы для разработчика ПО 35.5. Профессиональные ассоциации Связанные темы Web#ресурсы: www.cc2e.com Если вы так далеко продвинулись в чтении этой книги, то уже знаете, как много написано о практике эффективной разработки ПО. Доступной информации гораздо больше, чем можно представить. Все ошибки, которые вы делаете сейчас, люди уже сделали до вас. И если вы не хотите стать мальчиком для битья, то предпочтете читать их книги, чтобы не повторять их ошибки и не изобретать велосипед. Поскольку в этой книге упоминаются сотни других книг и статей по разработке ПО, трудно сказать, с чего начать чтение. Библиотека программиста включает в себя несколько видов информации. Основу составляют книги, объясняющие фун# даментальные концепции эффективного программирования. В других более под# робно рассматриваются технические, управленческие, интеллектуальные проблемы программирования. Подробные справочники по языкам, операционным системам, средам разработки и аппаратному обеспечению содержат информацию, полез# ную для конкретных проектов. Обычно книги последней категории представляют интерес в рамках одного проекта; в большей или меньшей степени они являются временными и здесь не обсуждаются. Что ка# сается других категорий, полезно иметь библиотечку, в которой основные виды деятельности по разработке ПО обсуждаются более глубоко: книги по выработке требований, конструированию, проектированию, управлению, тестированию и т. д. В следующих разделах подробно описываются ресурсы по конструированию, а http://cc2e.com/3560 http://cc2e.com/3581 ГЛАВА 35 Где искать дополнительную информацию 835 затем предлагается обзор материалов, относящихся к других вопросам разработ# ки ПО. В разделе 35.4 все ресурсы систематизированы и дан список литературы для разработчика ПО. 35.1. Информация о конструировании ПО Сначала я писал эту книгу, потому что не мог найти публи# каций, в которых бы всесторонне обсуждались вопросы конструирования ПО. За годы, прошедшие с момента пер# вого издания, появилось несколько хороших книг. Книга «Pragmatic Programmer» (Hunt and Thomas, 2000) заостряет внимание на деятельности, непосредственно связанной с кодированием, включая тестирова# ние, отладку, использование утверждений и т. д. Не вдаваясь в детали кода, она знакомит с многочисленными правилами создания хорошей программы В книге Джона Бентли «Programming Pearls», 2#е изд. (Bentley, 2000) обсуждаются искусство и наука проектирования ПО. Книга состоит из отлично написанных очерков, в которых глубокое понимание приемов эффективного конструирова# ния сочетается с увлеченностью этой темой. В каждой своей программе я использую что#нибудь полезное из очерков Бентли. Работа Кента Бека «Extreme Programming Explained: Embrace Change» (Beck, 2000) определяет подход к разработке ПО, опирающийся на конструирование. Как разъясняется в раз# деле 3.1, утверждения автора относительно экономики эк# стремального программирования не подтверждаются резуль# татами исследований, но многие из его рекомендаций полезны при конструиро# вании независимо от того, что применяется: экстремальное программирование или другой подход. В более специализированном труде Стива Мэгуаера «Writing Solid Code — Microsoft’s Techniques for Developing Bug#Free C Software» (Maguire, 1993) рассматривается практика конструирования ПО в масштабных коммерческих приложениях. Кни# га главным образом отражает опыт автора, приобретенный при работе над при# ложениями Microsoft Office. В ней также обсуждаются технические приемы про# граммирования на языке C. Автор в целом не затрагивает вопросы объектно#ори# ентированного программирования, но большинство рассматриваемых тем пред# ставляет интерес в любой среде. Брайан Керниган и Роб Пайк написали другую узкоспециализированную книгу — «The Practice of Programming» (Kernighan and Pike, 1999), в которой уделяют вни# мание будничным, но жизненно необходимым моментам в работе программис# та, практическим аспектам программирования, сокращая разрыв между академи# ческими знаниями в информатике и практическими навыками. В книге, предпо# лагающей знание языков C/C++, обсуждается стиль программирования, проекти# рование, отладка и тестирование. http://cc2e.com/3588 Перекрестная ссылка Об эконо- мике экстремального и быст- рого программирования см. cc2e.com/3545. 836 ЧАСТЬ VII Мастерство программирования Книга Сузан Ламмерс «Programmers at Work» (Lammers, 1986) не переиздавалась, но ее стоит найти. Она содержит интер# вью с высококвалифицированными программистами, в ко# торых раскрываются их личности, профессиональные привычки и философия программирования. Среди тех, кто дает интервью, такие светила, как Билл Гейтс (основатель Microsoft), Джон Уорнок (основатель Adobe), Энди Херцфельд (веду# щий разработчик ОС Macintosh), Батлер Лэмпсон (старший инженер компании DEC, теперь работающий в Microsoft), Уэйн Рэтлифф (изобретатель dBase), Дан Бриклин (изобретатель VisiCalc), и дюжина других. 35.2. Не связанные с конструированием темы Помимо основной литературы, рассмотренной в предыдущем разделе, здесь пред# ставлены книги, не имеющие прямого отношения к теме конструирования ПО. Обзорный материал Ряд книг позволяет взглянуть на процесс разработки ПО с разных сторон. Роберт Л. Гласс в работе «Facts and Fallacies of Software Engi# neering» (Glass, 2003) предлагает интересную трактовку традиционных представ# лений о возможном и невозможном в разработке ПО. Книга содержит много ука# зателей на дополнительные ресурсы. В книге «Professional Sofware Development» (2004) я рассматриваю практику раз# работки ПО в ее современном виде и размышляю о том, какой она должна быть в идеале. Книга «The Swebok: Guide to the Software Engineering Body of Knowledge» (Abran, 2001) разделяет на составляющие прикладную отрасль знаний, которая занима# ется оптимизацией и повышением эффективности разработки ПО, и погружает в детали конструирования ПО. Именно этот труд показывает, что в нашей облас# ти значительно больше достижений, чем можно представить. Книга Джеральда Вейнберга «The Psychology of Computer Programming» (Weinberg, 1998) наполнена замечательными анекдотами о программировании. Она несколько устарела, так как написана во времена, когда программирование считалось един# ственным аспектом создания ПО. Совет, прозвучавший при первом обсуждении этой книги в «ACM Computing Reviews», актуален и сегодня: «Каждый руководитель программистов должен иметь собственный экземпляр этой книги. Он должен читать ее, хранить у сердца, следовать ее наставлениям, а затем оставлять на своем столе, чтобы подчиненные могли ее украсть. Взамен украден# ным экземплярам следует подбрасывать новые, пока все не успокоятся». (Weiss, 1972). Если вы не смогли найти «The Psychology of Computer Programming», ищите «The Mythical Man#Month» (Brooks, 1995) или «PeopleWare» (DeMarco and Lister, 1999). Обе книги убеждают в том, что программирование — прежде всего результат че# ловеческой деятельности и лишь во вторую очередь — нечто связанное с компь# ютерами. http://cc2e.com/3549 http://cc2e.com/3595 |