Чтение онлайн

на главную

Жанры

Программист-прагматик. Путь от подмастерья к мастеру
Шрифт:

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

Другими словами, вы хотите убедиться в том, что вновь созданный подтип действительно "схож-с тем" (базовым) типом – что он поддерживает те же самые методы и эти методы имеют тот же смысл. Этого можно добиться при помощи контрактов. Контракт необходимо определить единожды (в базовом классе) с тем, чтобы он применялся к вновь создаваемым подклассам автоматически. Подкласс может (необязательно) использовать более широкий

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

Рассмотрим базовый класс Java, именуемый java.awt.Component. Вы можете обрабатывать любой визуальный элемент в AWT или Swing как тип Component и не знать, чем является подкласс в действительности – кнопкой, подложкой, меню или чем-то другим. Каждый отдельный элемент может предоставлять дополнительные, специфические функциональные возможности, но, по крайней мере, он должен предоставлять базовые средства, определенные типом Component. Однако ничто не может помешать вам создать для типа Component подтип, который предоставляет методы с правильными названиями, приводящие к неправильным результатам. Вы легко можете создать метод paint, который ничего не закрашивает, или же метод setFont, который не устанавливает шрифт. AWT не обладает контрактами, которые способны обнаружить факт нарушения вами соглашения.

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

/**

* @pre f != null

* @post getFont == f

 */

public void setFont(final Font f) {

//…

Реализация принципа ППК

Самая большая польза от использования принципа ПИК состоит в том, что он ставит вопросы требований и гарантий во главу угла. В период работы над проектом простое перечисление факторов – каков диапазон входных значений, каковы граничные условия, что можно ожидать от работы подпрограммы (или, что важнее, чего от нее ожидать нельзя), – является громадным шагом вперед в написании лучших программ. Не обозначив эти позиции, вы скатываетесь к программированию в расчете на совпадение (см. раздел "Программирование в расчете на стечение обстоятельств"), на чем многие проекты начинаются, заканчиваются и терпят крах.

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

Утверждения

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

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

Кроме того, отсутствует встроенный механизм «старых» значений; т. е. значений, которые существовали на момент входа в метод. При использовании утверждений, обеспечивающих соблюдение условий контрактов, к предусловию необходимо добавить программу, позволяющую сохранить любую информацию, которую вы намерены использовать в постусловии. Сравним это с iContract, где постусловие может просто ссылаться на "variabie@pre", или с языком Eiffel, который поддерживает принцип "old expression".

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

Поддержка ППК в языках программирования

Языки программирования, в которых имеется встроенная поддержка ППК (например, Eiffel и Sather[URL 12]) осуществляют автоматическую проверку предусловий и постусловий в компиляторе и исполняющей системе. В этом случае вы оказываетесь в самом выгодном положении, поскольку все базовые элементы программы (включая библиотеки)должны выполнять условия соответствующих контрактов.

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

Если вы работаете с языками С и С++, то попробуйте изучить Nana [URL 18]. Nana не осуществляет обработку наследования, но использует отладчик во время выполнения программы для отслеживания утверждений новаторским методом.

Для языка Java существует средство iContract [URL 17]. Оно обрабатывает комментарии (в формате JavaDoc) и генерирует новый исходный файл, содержащий логику утверждений.

Препроцессоры уступают встроенным средствам. Они довольно муторно интегрируются в проект, а другие используемые вами библиотеки останутся без контрактов. И тем не менее, они могут принести большую пользу; когда проблема обнаруживается подобным способом – в особенности та, которую по-другому найти просто невозможно, – это уже сродни работе волшебника.

Поделиться:
Популярные книги

Лорд Системы 12

Токсик Саша
12. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 12

Я – Орк. Том 3

Лисицин Евгений
3. Я — Орк
Фантастика:
юмористическое фэнтези
попаданцы
5.00
рейтинг книги
Я – Орк. Том 3

Темный Лекарь 2

Токсик Саша
2. Темный Лекарь
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Темный Лекарь 2

Наследница Драконов

Суббота Светлана
2. Наследница Драконов
Любовные романы:
современные любовные романы
любовно-фантастические романы
6.81
рейтинг книги
Наследница Драконов

Волк 2: Лихие 90-е

Киров Никита
2. Волков
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Волк 2: Лихие 90-е

Измена. Ты меня не найдешь

Леманн Анастасия
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Ты меня не найдешь

LIVE-RPG. Эволюция 2

Кронос Александр
2. Эволюция. Live-RPG
Фантастика:
социально-философская фантастика
героическая фантастика
киберпанк
7.29
рейтинг книги
LIVE-RPG. Эволюция 2

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Камень. Книга шестая

Минин Станислав
6. Камень
Фантастика:
боевая фантастика
7.64
рейтинг книги
Камень. Книга шестая

На границе империй. Том 10. Часть 3

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 3

70 Рублей

Кожевников Павел
1. 70 Рублей
Фантастика:
фэнтези
боевая фантастика
попаданцы
постапокалипсис
6.00
рейтинг книги
70 Рублей

Егерь

Астахов Евгений Евгеньевич
1. Сопряжение
Фантастика:
боевая фантастика
попаданцы
рпг
7.00
рейтинг книги
Егерь

Мерзавец

Шагаева Наталья
3. Братья Майоровы
Любовные романы:
современные любовные романы
эро литература
короткие любовные романы
5.00
рейтинг книги
Мерзавец

Приручитель женщин-монстров. Том 3

Дорничев Дмитрий
3. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 3