Т. Пратт, М. Зелковиц - Языки программирования - разработка и реализация (4-е издание_ 2002) (1160801), страница 77
Текст из файла (страница 77)
В этой главе мы рассмотрим, как можно разрабатывать абстракции, используя возможности подпрограмм, предоставляемые большинством языков программирования. В главе 7 мы распространим это понятие на такие возможности языка, как, например, реализованные в Ада пакеты (расчесе) или классы (с1азз) в С++ и ЯптаНГа! К которые помогают в реализации процесса инкапсуляции. 6.2.2. Сокрытие информации Для того чтобы понимать, как разрабатываются языковые средства, с помощью которых можно определять новые типы данных и новые операции, необходимо разобраться с понятием абстракции. Гели попытаться представить себе все детали большой, а порой и довольно скромных размеров программы, то станет очевидным, что одновременное их рассмотрение выходит за пределы интеллектуальных возможностей человека.
Чтобы созлать большую программу, приходится использовать принцип «разделяй и властвуйь. Программа делится на некоторое множество компонентов, называемых ~акже людулями. Каждый молуль выполняет ограниченное количество операций над ограниченным количеством данных. При проектировании модулей программы обычно придерживаются одного из следующих подходов к декомпозиции программы: 1) по футткциональттолту принципу; 2) по признаку используемых данных. Первый из этих двух подход<и использовался в 60-с гп как остювная модель разработки программы, и типичная структура подпрограмм, процедуры и функции явились результатом его применения, Проектирование программ по функциональному принципу считалось оптимальной методикой в течение многих лет. Чтобы понять, в чем недостаток этого подхода, рассмотрим упоминавшийся ранее тип дани ых группа. Чтобы осуществить декомпозицию программы на функциональные единицы, один программист может разработать функции регистрации, которые будут создавать группы, добавлять сптудетттое в группы и назначать преподавателя для группы.
Другой программист может взять эа основу функции поддержки класси, таки с как узап ить таоба в и ть студента изггв группу, проставить ответки каждому студенту и разослать счета на оплату каждого курса. В обоих случаях программист лолжен знать детали того, что собой представляют и группа, и студента. Однако, создавая модули, которые называются простыми абстракциями, можно избежать большей части отмеченных выше недостатков.
Построение абстракции группа и последующее ее использование в других программных модулях — как раз и есть такая простая абстракция. Все, что требуется понимать, чтобы пользоваться абстрактным типом данных, — это его специфика- 6.2. Абстрактные типы данных 275 ция; детали реализации скрыты и ими можно пе интересоваться. Гак, программист, разрабатывающий общую программу для распределения стулеитов по группам, может забыть, как именно оргаиьюонаиы группы, и помнить только о том, что можно включать стулеитов в группы, группы имеют своих преподавателей, пользуются аудиториями с опрелелепцыми номерами и т. д, Абстракция настолько распростраисиа в программировании, что часто иа иее пе обращают внимания. Представление программного обеспечения и аппаратной <асти н нплс слоев, описанное в главе 2, — лругой пример абстракции.
Блок-схема — это абстракция программной структуры управления ца уронив операторон. Методы разработки программ — пошаговая детализация, структурное, модул<а<ее и нисаогдя<цен програ,ижироаание — также связаны с созданием абстракций. В языках программирования абстракция поллержпвается двумя способами.
Вопервых, с помощью виртуального компьютера, более мощного и удобного в использовании, чем лежащий в его основе реальный аппаратный компьютер, язык испосрелстнспио предоставляет набор полезных абстракций, которые мы воспринимаем как свойства этого языка. Во-вторых, язык программирования предоставляет средства, позволяюьцпс самому программисгу конструировать абстракции, которые совместно формируют виртуальный компьютер, определяемый конкретной программой. Такими срелствами в различных языках явля<ется подпрограммы, библиотеки полпрограмм, определения тинов, классы и пакеты.
Термин сокрьапие инфорл<ации ио<ользустся для обозначения основного принципа, лежащего в основе проектирования абстракций, определяемых программистом: каждый такой программный компонент лолжеп щкколько возможно скрывать от пользоватслей информацию о своем внутреннем устройстве. Например, встроенная в язык фуикция вычисления квадратного корня янляется улач пой абстрактной операцией, поскольку она скрывает от пользователя детали прелставлеиия чисел и алгоритм нычислеиия кнадратюго корня.
Апалопщпо определяемый й пользователем тип данных может служить примером удачпой абстракции, если в итоге его можно использовать, пе зная конкретного представления объектов этого типа и алгоритмов, которые примецякнся для выполнения операций иал объектами этого типа. Когда информация и икаасулиронаяа н абстракцию, это означает, что пользователь: 1) пе иужлается в скрытой информации для того, чтобы пользоваться абстракцией; 2) не имеет возможности (ему ис позволено) пспосрсдстнеино использовать скргятую ииформащио или как-либо манипулировать ею, даже если бы ои и захотел этого.
Например, целочисленный тип данных в таких языках программирования, как ГОКТКАХ или С ис только скрывает детали г<редставлеция целых чисел н памяти, ио инкапсулирует это представление таким образом, что программист це имеет возможности манипулировать отдельными битами н прелстанлеиии целого числа (за исключением тех случаев, когда в механизме инкапсуляции даипого языка допущены какие-либо лефекты, делающие возможным иесаикциоииронаииый доступ к битовому представлению объектов данных). Но пользователю языков ЕОКТКАХ 276 Глава б, Инкапсуляция или С гораздо сложнее ин капсул и ровать представление нового типа данных. Хотя можно создать набор подпрограмм, которые позволяют создать тип группа и манипулировать им как абстракцией (то есть обеспечить сокрытие информации), при этом невозможно инкапсулировать представление данных, использованное при его реализации, таким образом, чтобы пользователь абстракции не смог написать другую подпрограмму, которая будет манипулировать группой непредусмотренным образом.
Например, сели список записавшихся на курс студентов будет представлен в ниде линейного массива целых чисел, то можно написать подпрограмму, которая к каждому из этих чисел прибавит 3. В терминах данной абстракции, где целые числа представляют идентификационные номера студентов, эта операция не имеет смысла, но в терминах выбранного способа представления (линейный массив целых чисел) эта операция абсолкп но правом< рва.
Инкапсуляция имеет большое значение при модификации программ, поскольку она существенно упрогцает этот процесс. Если бы нам удалось инкапсулировать тип данных группа, то можно было бы изменять представление объектов этого типа в любой момент, просто модифицируя подпрограммы, которые манипулируют объектами этого типа, так побы оци могли работать с их новым представлением взамен старого. Но если тип данных группа нс инкапсулирован, то другис части программы мокнут продолжать использовать его старое прсдставлсние.
Поэтому любые изменения в представлении этопз типа данных привели бгя к тому, что эти другие части программы не смогли функционировать, Часто очень трудно определить все подпрограммы, па которые (в отсутствие инкапсуляции) может повлиять изменение способа представления конкретных объектов данных. Поэтому изменения в нх представлении мокнут повлечь за собой трудноуловимые ошибки в тех частях программы, па которые, казалось бы, это изменение не может повлиять. Подпрограммы формируют основной механизм инкапсуляции, который присутствует почти во всех языках.
Современные механизмы, которые позволяют осуществлять инкапсуляцию определения целых юцюв данных, из тех языков, которые описаны в нашей книге, присутствуют только в Ада и С+а-'. Заметим, что сокрытие ияузормации — это прежде всего вопрос проектирования программ; сокрытие информации возможно в любой правильно спроектированной шрограгвлзе вне зависимости от используемого языка программирования. Инкапсуляция, однако, — э го прежде всего вопрос разработки конкретного языка; абстракция может быть эффективно инкансулированв только в том случае, если язык запрещает доступ к скрытой в абстракции информации.