Руководство по стилю программирования и конструированию по
Скачать 7.6 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 |