- •Содержание
- •2.3.1. Основные положения
- •2.3.4. Пример выполнения типового задания
- •2.6.1. Обзор методов упрощения условных выражений
- •1.Цель практических занятий
- •2. Основные положения
- •2.1. Тестирование на основе областей эквивалентности и структурное тестирование
- •2.1.1. Области эквивалентности
- •2.1.2. Структурное тестирование. Тестирование ветвей
- •2.1.3. Пример решения типового задания
- •2.2. Модульное тестирование программного обеспечения
- •2.2.1. Общий порядок тестирования по
- •2.2.2. Порядок тестирования классов
- •2.2.3. Пример выполнения типового задания
- •2.3. Интеграционное тестирование программного обеспечения
- •2.3.1. Основные положения
- •2.3.2. Идентификация взаимодействий
- •2.3.3. Выбор тестовых случаев
- •2.3.4. Пример выполнения типового задания
- •2.4. Рефакторинг программного кода. Составление методов
- •2.4.1. Основные идеи рефакторинга программного кода
- •2.4.2. Составление методов
- •2.4.2.1. Выделение метода (Extract Method)
- •Мотивация
- •Техника
- •Использование локальных переменных
- •2.4.2.2. Встраивание метода (Inline Method)
- •Мотивация
- •2.4.2.3. Встраивание временной переменной (Inline Temp)
- •Мотивация
- •Техника
- •2.4.2.4. Замена временной переменной вызовом метода (Replace Temp with Query)
- •Мотивация
- •Техника
- •2.4.2.5. Введение поясняющей переменной (Introduce Explaining Variable)
- •Мотивация
- •Техника
- •2.4.2.6. Расщепление временной переменной (Split Temporary Variable)
- •Мотивация
- •Техника
- •2.4.2.7. Удаление присваиваний параметрам (Remove Assignments to Parameters)
- •Мотивация
- •Техника
- •2.4.2.8. Замена метода объектом методов (Replace Method with Method Object)
- •Мотивация
- •Техника
- •2.4.2.9. Замещение алгоритма (Substitute Algorithm)
- •Мотивация
- •Техника
- •2.5. Рефакторинг программного кода. Перемещение функций между объектами
- •2.5.1. Обзор методов перемещения функций между объектами
- •2.5.2. Перемещение метода (Move Method)
- •2.5.3. Перемещение поля (Move Field)
- •2.5.4. Выделение класса (Extract Class)
- •2.5.5. Встраивание класса (Inline Class)
- •2.5.6. Сокрытие делегирования (Hide Delegate)
- •2.5.7. Удаление посредника (Remove Middle Man)
- •2.5.8. Введение внешнего метода (Introduce Foreign Method)
- •2.5.9. Введение локального расширения (Introduce Local Extension)
- •2.6. Рефакторинг программного кода. Упрощение условных выражений
- •2.6.1. Обзор методов упрощения условных выражений
- •2.6.2. Декомпозиция условного оператора (Decompose Conditional)
- •Мотивация
- •Техника
- •2.6.3. Консолидация условного выражения (Consolidate Conditional Expression)
- •Мотивация
- •Техника
- •2.6.4. Консолидация дублирующихся условных фрагментов (Consolidate Duplicate Conditional Fragments)
- •Мотивация
- •Техника
- •2.6.5. Удаление управляющего флага (Remove Control Flag)
- •Мотивация
- •Техника
- •2.6.6. Замена вложенных условных операторов граничным оператором (Replace Nested Conditional with Guard Clauses)
- •Мотивация
- •Техника
- •2.6.7. Замена условного оператора полиморфизмом (Replace Conditional with Polymorphism)
- •Мотивация
- •Техника
- •2.6.8. Введение объекта Null (Introduce Null Object)
- •Мотивация
- •Техника
- •3. Варианты заданий и порядок выполнения работы
- •Библиографический список
2.5.9. Введение локального расширения (Introduce Local Extension)
Используемый класс сервера требуется дополнить несколькими методами, но класс недоступен для модификации.
Создайте новый класс с необходимыми дополнительными методами. Сделайте его подклассом или оболочкой для исходного класса.
Рисунок 2.9 – Введение локального расширения
Мотивация
К сожалению, создатели классов не могут предоставить все необходимые методы. Если есть возможность модифицировать исходный код, то часто лучше всего добавить в него новые методы. Однако иногда исходный код нельзя модифицировать. Если нужны лишь один-два новых метода, можно применить «Введение внешнего метода» (Introduce Foreign Method). Однако если их больше, они выходят из-под контроля, поэтому необходимо объединить их, выбрав для этого подходящее место. Очевидным способом является стандартная объектно-ориентированная технология создания подклассов и оболочек. В таких ситуациях я называю подкласс или оболочку локальным расширением.
Локальное расширение представляет собой отдельный класс, но выделенный в подтип класса, расширением которого он является. Это означает, что он умеет делать то же самое, что и исходный класс, но при этом имеет дополнительные функции. Вместо работы с исходным классом следует создать экземпляр локального расширения и пользоваться им.
При использовании локального расширения поддерживается принцип упаковки методов и данных в виде правильно сформированных блоков. Если же продолжить размещение в других классах кода, который должен располагаться в расширении, это приведет к усложнению других классов и затруднению повторного использования этих методов.
Если стоит вопрос выбора между подклассом и оболочкой, следует учитывать, что использование подкласса связано с меньшим объемом работы. Самое большое препятствие на пути использования подклассов заключается в том, что они должны применяться на этапе создания объектов. Если есть возможность управлять процессом создания, проблем не возникает. Они появляются, если локальное расширение необходимо применять позднее. При работе с подклассами приходится создавать новый объект данного подкласса. Если есть другие объекты, ссылающиеся на старый объект, то появляются два объекта, содержащие данные оригинала. Если оригинал неизменяемый, то проблем не возникает, т. к. можно благополучно воспользоваться копией. Однако если оригинал может изменяться, то возникает проблема, поскольку изменения одного объекта не отражаются в другом. В этом случае надо применить оболочку, тогда изменения, осуществляемые через локальное расширение, воздействуют на исходный объект, и наоборот.
Техника
- Создайте класс расширения в виде подкласса или оболочки оригинала.
- Добавьте к расширению конвертирующие конструкторы.
Конструктор принимает в качестве аргумента оригинал. В варианте с подклассом вызывается соответствующий конструктор родительского класса; в варианте с оболочкой аргумент присваивается полю для делегирования.
- Поместите в расширение новые функции.
- В нужных местах замените оригинал расширением.
- Если есть внешние методы, определенные для этого класса, переместите их в расширение.
