Опубликован: 23.10.2005 | Доступ: свободный | Студентов: 4087 / 201 | Оценка: 4.44 / 4.19 | Длительность: 33:04:00
Специальности: Программист
Лекция 1:

Объектно-ориентированная методология: Правильно применяйте метод

Лекция 1: 1234 || Лекция 2 >

Как создавать хорошие правила: советы советчикам

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

Необходимость методологических руководств

Методология разработки ПО не является новой областью. Ее истоки восходят к известной работе Дейкстры "Go To Statement Considered Harmful" ( О вреде оператора Go To ) и последующим работам этого же автора и его коллег по структурному программированию. Но не все последующие методологические работы поддерживают достигнутый уровень стандартов.

На самом деле довольно просто запретить ту или иную программистскую конструкцию, но есть величайшая опасность в создании бесполезных правил, плохо обдуманных и даже вредных. Следующие заповеди, основанные на анализе роли методологии в создании ПО, помогут нам избежать подобных ловушек.

Теория

Первая обязанность советчика - давать совет, согласующийся с предметной областью:

Теоретический базис: принцип методологии

Правила методологии ПО должны базироваться на теории предметной области.

Пример Дейкстры может служить хорошей иллюстрацией. Он не пытался атаковать оператор Goto по причинам вкуса или чьих либо мнений - он приводил тщательно выверенную систему выводов. Кто-то мог не соглашаться с некоторыми из аргументов, но не мог отрицать, что заключение построено на хорошо продуманном взгляде на процесс разработки ПО. Не считаться с точкой зрения Дейкстры можно лишь при обнаружении изъяна в его теории и построении своей собственной теории для этого случая.

Практика

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

Практический базис: принцип методологии

Правила методологии ПО должны основываться на широком практическом опыте.

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

Такой опыт должен включать все этапы жизненного цикла ПО: анализ, проектирование, реализацию и, конечно же, сопровождение (заключительный аккорд, который только и показывает, выдержали ли ваши решения, принятые на предыдущих этапах, проверку временем и изменениями).

Опыта, анализа или даже анализа и проектирования явно недостаточно. Не один раз приходилось видеть, как консультанты по анализу выполняли свою работу, получали плату, и оставляли компанию с не более чем схемами с квадратиками и стрелками - документом анализа. А затем компания должна была извлекать нечто полезное из этих кусочков и делать свою трудную работу; иногда работа аналитиков оказывалась полностью бесполезной, поскольку не учитывала важных практических ограничений. Подход "только анализ" противоречит фундаментальным идеям бесшовности (seamlessness) и обратимости (reversibility), интегрированному жизненному циклу, характерному для объектной технологии, где анализ и проектирование свиваются с реализацией и сопровождением. Кто не прошел все этапы этого пути, вряд ли может давать методологические советы.

Повторное использование

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

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

Повторное использование: принцип методологии

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

Типология правил

Обратимся теперь к форме методологических правил. Какой вид советов является эффективным?

Правило может быть рекомендацией ( advisory ) - приглашением следовать определенному стилю, или абсолютным ( absolute ) - предписывающим выполнять работу определенным образом. Правило может быть выражено в положительной ( positive ) форме - говорящей, что следует делать, или в отрицательной ( negative ) форме - чего не следует делать. Это дает нам четыре вида:

Классификация методологических правил

  • Абсолютно положительное: "Всегда делай a ".
  • Абсолютно отрицательное: "Никогда не используй b ".
  • Рекомендательно положительное: "Используй c, если это возможно".
  • Рекомендательно отрицательное: "Избегай d, если это возможно".

В каждом случае требования слегка отличаются.

Абсолютная положительность

Правила абсолютно положительного вида наиболее полезны для разработчиков ПО, так как дают точное и недвусмысленное руководство к действию.

К сожалению, они являются наиболее редким видом правил, появляющимся в методологической литературе. Частично этому есть разумные причины - для точных советов можно написать соответствующий инструментарий, автоматически выполняющий требуемую задачу, избавляя тем самым от необходимости давать методологические указания. Но часто за этим стоит осторожность методологов, которые, подобно адвокатам, никогда не говорящим "да" или "нет", опасаются последствий, когда их клиент будет действовать, полагаясь на их рекомендации.

Абсолютная положительность: принцип методологии

При выработке методологических правил отдавайте предпочтение абсолютной положительности. Для каждого такого правила рассмотрите возможность его автоматического выполнения благодаря специальному инструментарию или конструкциям языка.

Абсолютная отрицательность

Абсолютная отрицательность - весьма чувствительная область. Можно только пожелать, что всякий, кто рискнет пойти по стопам Дейкстры, проявил бы ту же тщательность в проверке отрицательного эффекта, как это сделал Дейкстра по отношению к оператору Goto. Следующее предписание справедливо для таких правил:

Абсолютная отрицательность: принцип методологии

Любое абсолютное отрицание должно сопровождаться точным пояснением того, почему отвергаемый механизм является плохой практикой. Это пояснение должно дополняться точным описанием механизма, заменяющего отвергаемый.

Рекомендации

Рекомендательные правила, положительные или отрицательные, несут в себе риск бесполезности.

Чтобы отличить принцип от обычной банальности ( platitude ), следует рассмотреть отрицание: для принципов отрицание имеет смысл независимо от того, согласны вы с ним или нет. Например, часто цитируемый методологический совет: "Используйте имена переменных, имеющие смысловое содержание", - не является принципом с этой точки зрения, так как никто в здравом уме не будет выбирать бессмысленные имена переменных. Для превращения этого правила в принцип, следует задать точный стандарт именования переменных. Конечно, поступив так, вы обнаружите, что некоторые читатели не будут согласны с предложенным стандартом, - вот почему банальности более комфортабельны, но методологи должны брать на себя подобные риски.

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

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

Рекомендательные правила: принцип методологии

Создавая рекомендательные правила (положительные или отрицательные), используйте принципы, а не банальности. Для того чтобы отличить одно от другого, используйте отрицание.

Вот пример отрицательной рекомендации, извлеченный из обсуждения преобразования типов ( casts ) в одном из справочников по C++:

Явного преобразования типов лучше избегать. Использование кастинга подавляет проверку типов, обеспечиваемую компилятором, и тем самым может приводить к сюрпризам, если только программист действительно не был прав.

Все это не сопровождается пояснением, как же выяснить, что " программист действительно был прав ". Так что читателю предлагается не использовать некоторый механизм языка ( type casts ), предупреждая, что это может быть опасно и " приводить к сюрпризам ", неявно заявляя, что иногда этот механизм следует применять, не давая никакого указания, как различать случай легитимного использования.

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

Исключения

Многие правила имеют исключения. Но если вы представляете методологическое правило и желаете указать, что оно не всегда применимо, следует точно определить исключения. В противном случае правило будет неэффективным: каждый раз, когда разработчик действительно нуждается в совете, он будет судорожно размышлять применимо правило или нет.

В одной из статей по методологии ПО после представления довольно строгого множества правил приводится следующий абзац:

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

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

Что ошибочного, если исключения не присутствуют в общих руководствах? Поскольку проектирование ПО является сложной задачей, то иногда необходимо (хотя всегда нежелательно) к абсолютно положительному правилу " Всегда делай X в ситуации A " или к абсолютно отрицательному " Никогда не делай Y в ситуации A " добавлять квалификацию " за исключением случаев B , C и D ". Такое квалифицированное правило остается абсолютно положительным или отрицательным: просто его область применения сужается, теперь это не все A, но A лишенное B, C и D. Расплывчатая формулировка исключений неприемлема (" в некоторых ситуациях потери могут быть больше преимуществ " - что это за ситуации?). Позже в цитируемой статье показан пример, нарушающий правило, но исключение проверяется в терминах, специально подобранных для данного случая, а оно должно быть частью правила:

Включение исключений: принцип методологии

Если методологическое правило представляет общеприменимое руководство, предполагающее исключения, то исключения должны быть частью правила.

Если исключения включены в правило, то они перестают быть исключениями из правила! Вот почему в приведенном принципе говорится о "руководстве", связанном с правилом. У руководства могут быть исключения, но они не являются исключениями для правила. В правиле " Переходите улицу только при зеленом свете светофора, если только светофор в порядке " руководство "переходите улицу только на зеленый" имеет исключения, но у правила как у целого исключений нет.

Этот принцип возвращает каждому правилу форму: "Делай это..." абсолютно положительного правила или "Не делай этого..." абсолютно отрицательного.

Сомнения - это прекрасное качество во многих жизненных обстоятельствах, но не тогда, когда оно встречается в методологических правилах. Почти каждый согласится с тем, что сомневающийся, не говорящий ничего определенного методолог, хуже выдающегося, кто может случайно ошибиться. Советы первого, в большей части, бесполезны, поскольку никогда нельзя определить, применимы ли они к данной ситуации. Если при изучении правила вы не согласны с ним, то аргументам автора следует противопоставить собственные. Независимо от исхода вы чему-нибудь научитесь: либо вы ошиблись и тогда вы придете к более глубокому пониманию правила и его применимости к вашей проблеме, либо обнаружите ограничения правила.

Абстракция и точность

Общая суть последних нескольких принципов состоит в том, что правила должны быть точными и директивными.

Конечно, это в большей мере относится к правилам, чем к общим руководствам по проектированию. Когда ищешь советы по выявлению того, какими должны быть классы проекта, или по построению нужной иерархии наследования, то нельзя ожидать рецептов вида: шаг-1, шаг-2, шаг-3.

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

Если это необычно, зафиксируй это

Совет по кастингу типов C++, процитированный выше, иллюстрирует проблему, общую для советов отрицательного типа: подобные рекомендации своим существованием обязаны ограничениям соответствующего инструментария или языка. Для совершенного инструментария никогда не приходится давать отрицательные советы; каждое свойство такого инструментария сопровождается точным определением, когда оно применимо, а когда нет - критерий абсолютного вида. Поскольку совершенства в мире нет, то в хорошем инструментарии число отрицательных советов должно оставаться относительно небольшим. Если при изучении нового средства приходится часто сталкиваться с комментариями в форме "Пытайтесь избегать этого механизма, если только в нем нет обязательной необходимости", то это в большей степени говорит о проблеме с изучаемым инструментарием, а не о том, чтобы чему-нибудь вас обучить.

В таких ситуациях вместо того, чтобы давать подобные советы, лучше улучшить само средство или построить лучшее.

Типичные фразы, свидетельствующие о подобной ситуации:

...разве только вы знаете, что делаете.
...разве только вы абсолютно должны.
Избегайте... если можете.
Не пытайтесь...
Обычно это предпочтительно, но...
Лучше этого избегать...

Литература по C/C++/Java имеет особую любовь к таким формулировкам. Типичным является совет "Не пишите в поля данных ваших структур, если только вы не должны" от того же эксперта по C++, предупреждавшего в одной из предыдущих лекций о нежелательности использования ОО-механизмов.

Этот совет загадочен. По каким причинам разработчики не должны записывать данные?

Нарастающая Проблема Программистов, Пишущих в Поля Структуры Данных, Не Заботящихся Об Индустрии ПО США. Почему они делают это? Говорит Джил Добраядуша, Старший Программист из Санта Барбары, Калифорния: "Мое сердце склонно к добрым делам. В пространстве свопинга чувствуется такое одиночество! Я считаю своим долгом записывать данные в поле каждого из моих объектов, по меньшей мере один раз в день, даже если приходится писать его собственное значение. Иногда я возвращаюсь во время уикенда, просто чтобы сделать это". Действия программистов, подобных Джилу, приводят к растущим озабоченностям поставщиков ПО, заявляющих о необходимости специальных мер, чтобы справиться с этими проблемами.

Другая известная ситуация возникает при попытках с помощью методологических советов устранить пороки языка разработки, - перекладывая ответственность за чьи-то ошибки на пользователей языка. В одной из предыдущих лекций (Исключения) цитировался совет программистам Java (" однако программист может повредить объекты "), направленный против прямого присваивания полю a.x := y как нарушающий принципы скрытия информации. Это удивительный подход; если вы думаете, что конструкция плоха, то зачем включать ее в язык программирования, а затем писать книгу, предписывающую будущим пользователям языка избегать ее.

Закон Деметры, цитированный ранее, дает еще один пример. Он ограничивает тип x в вызове x.f (...), появляющемся в программе r класса C: типами аргументов r ; типами атрибутов C ; типами создания (типами u в create u ) для инструкций создания, появляющихся в r. Такие правила, если они обоснованы, должны быть частью языка. Но сами авторы полагают, что это было бы чересчур жесткое требование. Это правило делает невозможным, например, написать вызов my_stack.item.some_routine, применяющий some_routine к элементу в вершине стека.

Исследуя возможные причины появления этого закона и его исключений, можно предположить, что авторы не рассматривали понятия селективного выбора, позволяющего предоставлять разные права доступа разным клиентам. С этим механизмом необходимость в законах, подобных закону Деметры, просто бы отпала.

Эти наблюдения приводят к последнему принципу:

Фиксируйте все, что приводит к поломкам: принцип методологии

Если вы встретились с необходимостью многих отрицательных советов:

  • L Исследуйте поддерживающий инструментарий или язык, чтобы определить, не связано ли это с дефектами используемых средств.
  • L Если так, рассмотрите возможность изменений.
  • L Рассмотрите также возможность исключить проблему, переключившись на лучшее средство.
Лекция 1: 1234 || Лекция 2 >