Изменить стиль страницы

Сильные связи между частями должны выглядеть, как сильные связи; слабые связи должны выглядеть, как более слабые. Устойчивые объекты должны быть показаны сплошными фигурами, а динамические объекты должны выражать смысл активности или изменяемости. Например, наследование одним классом свойств и характеристик другого класса означает, что подкласс в большой степени зависит от родительского класса — подобно тому как генетические особенности ребенка сильно зависят от особенностей обоих родителей. Для точного отражения характеристик программного обеспечения, использующего наследование, этот механизм должен быть показан более четко, чем передача сообщения объекту или ссылка на него как на атрибут (Page-Jones, Constantine и Weiss, 1990 [57]).

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

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

Подумайте об этом.

Из журнала Software Development, том 2, № 3, март 1994 г.

21

Методичное сумасшествие

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

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

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

Шаг первый

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

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

Разбиение

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

Мы имеем. Если мы сталкиваемся с неподатливой сложностью, то что мы делаем? То же, что делали наши предки, когда имели дело с огромной ногой мастодонта, которую нельзя проглотить: мы откусываем часть и начинаем ее пережевывать. Для того чтобы справиться с большой задачей, мы разбиваем ее на более мелкие. Здесь есть некоторая магия ума, махание руками, которое, вообще говоря, нисколько не уменьшает сложность задач, возникающих при программировании. Но зачастую это так или иначе помогает, создавая у перегруженного разработчика иллюзию, что большие, сложные системы можно построить из множества маленьких, простых кусочков кода.

Иногда мы, словно неудачливые начинающие волшебники, обнаруживаем, что разбиение большой задачи на части лишь все перемешало. Большие задачи становятся меньше, если разбиваются только до той степени, когда отдельные ее части перестают быть тесно связанными друг с другом и могут быть рассмотрены более или менее независимо. При этом каждая часть разрабатывается и программируется как самостоятельная задача меньшего масштаба, решить которую вполне по силам. Все эффективные методы разработки в том или ином виде содержат некоторые правила или указания, в которых говорится о необходимости «делать края ровными», когда вы выделяете из задачи ее части. Целое разделяется на элементы, каждый из которых может быть осмыслен как самостоятельная подзадача.

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

В традиционном структурном проектировании эти принципы воплощены в общепризнанных понятиях связывания и сцепления. Связывание — это мера взаимосвязи и взаимозависимости между компонентами программного обеспечения; сцепление определяет, в какой мере компонент является четко определенным функциональным целым. Эти давно известные понятия были заново открыты в новом мире объектной технологии. Хорошие объектно-ориентированные методы напоминают программистам об уменьшении объектного связывания и об увеличении сцепления методов с помощью инкапсуляции всего необходимого в отдельный объект (Henderson-Sellers и Constantine, 1996 [39]). В противном случае вы получите запутанный клубок переплетенных между собой объектов, не поддающихся анализу и повторному использованию.

Структурное соответствие