Объектно-ориентированное программирование

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

Термин класс используется для описания множества объектов с похожим поведением. Мы увидим в последующих главах, что класс применяется как синтаксический механизм почти во всех объектно-ориентированныхязыках. Конкретные представители класса называются экземплярами. Заметим, что поведение ассоциировано с классом, а не с индивидуальными представителями. То есть все экземпляры класса воспринимают одни и те же команды и выполняют их сходным способом. С другой стороны, состояние является индивидуальным. Мы видим это на примере различных экземпляров классаRecipe. Все они могут выполнять одни и те же действия(редактирование, вывод на экран, печать), но используют различные данные. Мы рассмотрим концепцию класса более подробно в главе3.

2.7.3. Зацепление и связность

Двумя важными понятиями при разработке программ являются зацепление (coupling) и связность(cohesion). Связность— это мера того, насколько отдельная компонента образует логически законченную, осмысленную единицу. Высокая связность достигается объединением в одной компоненте соотносящихся(в том или ином смысле) друг с другом функций. Наиболее часто функции оказываются связанными друг с другом при необходимости иметь доступ к общим данным. Именно это объединяет разные части компонентыRecipe.

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

модификации и мешают дальнейшей разработке или повторному использованию в других программах.

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

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

2.7.4. Интерфейс и реализация модуля — принципы Парнаса

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

 

Например предположим, что шесть компонент приложенияIIKH создаются шестью программистами. Программист, разрабатывающий компонентуMeal, должен обеспечить просмотр базы данных с рецептами и выбор отдельного рецепта при составлении блюда. Для этого компонентаMeal просто вызывает функциюbrowse, привязанную к компонентеRecipe Database. Функцияbrowse возвращает отдельный рецептRecipe из базы данных.

Все это справедливо вне зависимости от того, как конкретно реализован внутриRecipe Database просмотр базы данных.

Мы прячем подробности реализации за фасадом интерфейса. Происходит маскировка информации. Говорят, что компонента инкапсулирует поведение, если она умеет выполнять некоторые действия, но подробности, как именно это делается, остаются скрытыми. Это естественным образом приводит к двум различным представлениям о программной системе. Вид со стороны интерфейса— это лицевая сторона; ее видят другие программисты. В интерфейсной части описывается, что умеет делать компонента. Вид со стороны реализации— это «изнанка», видимая только тем, кто работает над конкретной компонентой. Здесь определяется, как компонента выполняет задание.

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