ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.11.2023

Просмотров: 783

Скачиваний: 6

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

392 ли, что такое разделение жизненно важно для долго живущих систем.
Выделение иерархии (Extract Hierarchy) упрощает чрезмерно сложные классы путем превращения их в группы подклассов.
1. Разделение наследования (Tease Apart Inheritance). Наследование способствует написанию чрезвычайно «сжатого» кода в подклассах.
Механизм наследования обладает такой мощью, что случаи его непра- вильного применения не должны удивлять. Неправильное употребление накапливается постепенно. Например, разработчик вводит небольшой класс для решения простой задачи, потом добавляет другие подклассы для решения той же задачи в других местах иерархии. И через месяц
(или год) имеет запутанное наследование, которое представляет собой потенциальный источник неприятностей, потому что оно приводит к дублированию кода (как говорит М. Фаулер, – бичу программистов).
Оно осложняет модификацию, потому что стратегии решения опреде- ленного рода проблемы распространены по всей программе. Наконец, труднее понимать результирующий код.
Легко можно обнаружить одну иерархию наследования, которая ре- шает две задачи. Если у каждого подкласса на определенном уровне иерархии есть подклассы, имена которых начинаются с одинаковых прилагательных, то, вероятно, делается два дела с помощью одной ие- рархии. Таким образом, если есть иерархия наследования, которая вы- полняет одновременно две задачи, М. Фаулер рекомендует создать две иерархии и использовать делегирование для вызова одной из другой.
2. Преобразование процедурного проекта в объекты (Convert
Procedural Design to Objects). Часто приходится сталкиваться с пробле- мой, когда код процедурного вида надо сделать более объектно- ориентированным. Типичную ситуацию представляют длинные проце- дурные методы в классе, хранящем мало данных, и «немые» объекты данных, в которых нет ничего, кроме методов доступа к полям. Если надо преобразовать чисто процедурную программу, то и «немых» объ- ектов может не оказаться, но для начала и это неплохо. Нельзя утвер- ждать, что объектов с поведением и малым количеством данных (или полным их отсутствием) вообще быть не должно. Часто используются маленькие объекты стратегий, когда требуется варьировать поведение.
Однако такие процедурные объекты обычно невелики и применяются, когда возникает особая потребность в гибкости.
Если имеется код, написанный в процедурном стиле, М. Фаулер ре- комендует преобразовать записи данных в объекты, разделить поведе- ние и переместить поведение в объекты.
3. Отделение предметной области от представления (Separate
Domain from Presentation). В разговорах об объектах можно услышать о
«модели-представлении-контроллере» (MVC) [1]. Эта идея послужила фундаментом связи между графическим интерфейсом пользователя
(GUI) и объектами предметной области в Smalltalk-80. В основе MVC лежит разделение кода пользовательского интерфейса (представления, называвшегося раньше view, а сейчас чаще presentation) и логики пред- метной области (модели - model). Классы представления содержат толь-


393 ко ту логику, которая нужна для работы с интерфейсом пользователя.
Объекты предметной области не содержат кода визуализации, зато со- держат всю бизнес-логику.
В результате сложная программа разделяется на части, которые проще модифицировать. Кроме того, появляется возможность сущест- вования нескольких представлений одной и той же бизнес-логики. Тот, кто имеет опыт работы с объектами, пользуется таким разделением ин- стинктивно, и оно доказало свою ценность. Но многие из тех, кто рабо- тает с GUI, не придерживаются такой архитектуры. В большинстве сред с GUI «клиент/сервер» реализована двухзвенная конструкция: данные находятся в базе данных, а логика находится в классах представления.
Среда часто навязывает такой стиль проектирования, мешая поместить логику в другое место.
Java – правильная объектно-ориентированная среда, позволяющая создавать невизуальные объекты предметной области, содержащие биз- нес-логику. Однако часто можно столкнуться с кодом, написанным в двухзвенном стиле. Имеются классы GUI, содержащие логику предмет- ной области. В таких случаях рекомендуется выделить логику предмет- ной области в отдельные классы предметной области.
4. Выделение иерархии (Extract Hierarchy). При эволюционном про- ектировании класс часто представляется как реализация одной идеи, а впоследствии обнаруживается, что на самом деле он реализует две или три идеи, а то и все десять. Сначала создается простой класс. Через не- которое время разработчик замечает, что если добавить в него один флаг и пару проверок, то можно его использовать еще в одном случае.
Через месяц обнаруживается еще одна такая возможность, а через год наступает полная неразбериха: всюду раскиданы флаги и условные вы- ражения.
Столкнувшись с такой ситуацией, надо найти стратегию, позволяю- щую расплести отдельные пряди. Описываемая в [32] стратегия дейст- вует, если только условная логика сохраняет статичность в течение сро- ка жизни объекта, в противном случае, прежде чем начать отделять од- ни случаи от других, может потребоваться провести «Выделение клас- са» (Extract Class). «Выделение иерархии» ( Extract Hierarchy ) - такой рефакторинг, который нельзя завершить за один день. Для распутыва- ния сложного проекта могут потребоваться недели или месяцы.
Поэтому если есть класс, выполняющий слишком много работы, частично или полностью через многочисленные условные операторы, рекомендуется создать иерархию классов, в которой каждый подкласс представляет конкретный случай.
1   ...   29   30   31   32   33   34   35   36   37

8.6. Архитектурный рефакторинг. Архитектурные паттерны
8.6.1. Когда нужен архитектурный рефакторинг
Потребность в изменении существующей программной системы мо- жет возникнуть в ходе решения широкого круга задач по ее модерниза-

394 ции [14, 15]. В общем случае изменения существующей программной системы затрагивают не только программный код, но и все остальные артефакты, связанные с трансформируемой программной системой.
Часто существенным является изменение архитектуры программной системы. В качестве примеров можно привести следующие сценарии, требующие изменения архитектуры существующей ПС.
1. Преобразования, обусловленные функциональными изменениями
ПС. Желательно, чтобы внедрение новой функциональности не затро- нуло существующую логику системы. Также желательно, чтобы слож- ность внедрения новой функциональности в существующую систему не превышала существенным образом сложность реализации этой функ- циональности в рамках нового проекта. Изменение существующей ар- хитектуры – хороший шаг на пути внедрения новой функциональности, облегчающий и дальнейшую эволюцию системы.
2. Смена платформы ПС. Смена платформы ПС (как аппаратной, так общего программного обеспечения, в частности операционной системы) должна минимально затрагивать существующий код. Желательно огра- ничиться изменениями только в узкой платформенно-зависимой про- слойке системы. Выделение такой прослойки – архитектурная задача.
Ее решение всегда сопряжено с необходимостью изменения архитекту- ры.
3. Обновление технологии разработки программного продукта, свя- занное, например, с переходом компонентное программирование, вне- дрением комплексной среды коллективной разработки с возможностя- ми гибкого, формального и смешанного планирования и ведения отчет- ности, доступными на одной платформе, например, IBM Rational Team
Concert .
4. Преобразования, связанные с реорганизацией компании, ведущей разработку. Преобразования, связанные с реорганизацией компании, ведущей разработку. Примером, такой реорганизации может стать аут- сорсинг. Решение об использовании аутсорсинга – типичный шаг по оптимизации производства. К сожалению, этот шаг зачастую затрудня- ется проблемой выделения и передачи компонентов для внешней разра- ботки. Изменение архитектуры программной системы способно облег- чить решение этой задачи.
При описании методов рефакторинга принято использовать частич- но формализованный формат – шаблон или паттерн [30, 36]. Это повто- римая архитектурная конструкция, представляющая собой решение проблемы проектирования в рамках некоторого часто возникающего контекста. Обычно шаблон не является законченным образцом, который может быть прямо преобразован в код; это лишь пример решения зада- чи, который можно использовать в различных ситуациях. Объектно- ориентированные шаблоны показывают отношения и взаимодействия между классами или объектами, без определения того, какие конечные классы или объекты приложения будут использоваться [36]. «Низко- уровневые» шаблоны, учитывающие специфику конкретного языка про- граммирования, называются идиомами. Это хорошие решения проекти-


395 рования, характерные для конкретного языка или программной плат- формы, и потому не универсальные. На наивысшем уровне существуют архитектурные шаблоны, они охватывают собой архитектуру всей про- граммной системы.
Любой паттерн описывает и именует типовую задачу, которая по- стоянно возникает в работе, а также принцип ее решения, причем таким образом, что это решение можно использовать потом снова и снова.
Паттерн именует, абстрагирует и идентифицирует ключевые аспекты структуры общего решения. Помимо прочего, паттерны формируют словарь в проблемной области и позволяют двум специалистам в этой области именовать типовые решения и понимать друг друга, не объяс- няя каждый раз суть самих решений.
Например, в [32] паттерн имеет следующую структуру: название паттерна; краткая сводка ситуаций, в которых требуется данный метод; мотивировка применения; пошаговое описание применения метода рефакторинга.
Известно, что рефакторинг объектно-ориентированного кода заре- комендовал себя как эффективный способ решения задач эволюции и сопровождения программ. Однако, и это отмечается в статьях М. Ксен- зова [14, 15], опубликованных в 2004 году, практически не существует исследований, освещающих рефакторинг на более высоком уровне аб- стракции – уровне архитектуры ПО. Ситуация мало изменилась и к на- стоящему времени. Поэтому вызывает интерес, возможен ли перенос данной методологии на более высокий уровень абстракции, с целью получения аналогичной методики систематического изменения архи- тектуры ПО?
Специфика исследования и трансформации архитектуры программ- ного обеспечения заключается в том, что архитектура не имеет явного представления, за исключением, может быть, тех случаев, когда она явно задокументирована. Однако даже в последнем, случае трудно га- рантировать соответствие задокументированной архитектуры фактиче- ской высокоуровневой логической структуре, которая на самом деле существует. Способом описания архитектуры и ее изменений могут стать структурные модели. В настоящее время существует большое ко- личество нотаций и инструментов, поддерживающих структурное моде- лирование программных систем. В свете соответствия модели фактиче- ской структуре существующего кода представляется исключительно важной возможность автоматического извлечения таких моделей из ко- да программных систем, поскольку в этом случае гарантирует их точ- ность.
8.6.2. Построение архитектуры ПС по ее программному коду
Данной задаче посвящен ряд работ. Одной из них, наиболее инте- ресной и универсальной по предлагаемому подходу является статья В.
Миронова [17]. В этой работе рассматривается технология анализа про-


396 грамм большого размера на основе построения графов, что обеспечива- ет навигацию по исходным файлам с показом необходимых свойств
(например, используемых классов, методов, функций и др.). Предвари- тельно стоит рассмотреть возможные подходы и инструментальные средства анализа и формального представления текстов программ.
1. Язык UML, предназначенный для определения, визуализации, конструирования и документирования артефактов программных систем.
Он позволяет в объектно-ориентированном виде описать систему прак- тически со всех возможных точек зрения, в том числе и разные аспекты поведения системы. Основной недостаток – неточная семантика. Язык
UML предназначен для графического представления системы на сред- нем и высоком уровнях, но малоэффективен для описания детальной логики программ нижнего уровня.
2. CASE-технологии – программные комплексы, автоматизирующие технологический процесс анализа, проектирования, разработки и сопро- вождения сложных программных систем. CASE-технологии использо- вались в реинжиниринге с момента их появления. Однако по своей при- роде CASE-средства малопригодны для низкоуровневого описания структуры ПС. Кроме того, они предполагают рассмотрение ПС со сто- роны организации бизнес-процессов, потоков и создания оптимальной
ИС для предприятия. Несмотря на высокие потенциальные возможно- сти CASE-технологии далеко не все разработчики ИС, использующие
CASE-средства, достигают ожидаемых результатов.
3. Комплекс программ построения графов Graphviz [4], разработан- ный специалистами лаборатории AT&T пакет утилит по автоматиче- ской визуализации графов, заданных в виде описания на языке «dot». В пакет утилит Graphviz входит автоматический визуализатор «dot» для формирования ориентированных графов на основе входного текстового описания (на специальном языке описания объектов, связей и их харак- теристик) в виде графического, векторного или текстового файла. Дан- ная технология является вспомогательным средством, обеспечивающим поддержку оптимального расположения вершин графа.
4. Kscope – программа для исследования и редактирования исходных текстов больших проектов на языке C 9 (Сейчас KScope не поддержива- ется. Прошлые релизы и репозитарий исходного кода еще доступны на
SourceForge.net). Она позволяет построить граф-дерево вызовов, кото- рый наглядно показывает отношения между функциями. В Kscope ис- пользуется свой подход к процессу визуализации: составление и вызов запроса. Недостатками данного подхода является малая информатив- ность (очень сложно увидеть на графе всю программу целиком) и огра- ниченность синтаксисом языка C.
Рассмотрим принципы подхода к решению задачи построения архи- тектуры ПС по ее программному коду [17]. Одним из способов прове- дения анализа является формирование графов с различным уровнем отображения внутренних объектов и связей. Модель данных большой программной системы, реализованной на языках программирования
С/С++, представляет собой наборы директорий, содержащих различные