Назад Оглавление Вперед
На головную страницу М.М.Горбунов-Посадов
 
РАСШИРЯЕМЫЕ ПРОГРАММЫ
 

 Г л а в а  7
НЕВЫДУМАННЫЕ ИСТОРИИ
 
7.2. Атрибут платежа
 

 

7.2. Атрибут платежа

      Delphi — одна из первых мощных инструментальных сред визуального программирования. Типичный сеанс работы с Delphi начинается с того, что программист выбирает из меню и расставляет на первоначально пустой панели разнообразные необходимые для будущей программы примитивы MS Windows: кнопки, поля ввода, основное меню, линейки прокрутки и т. д. Затем, указав на некоторый примитив, он может поменять его атрибуты или записать фрагмент алгоритма, реализующий реакцию указанного примитива на какое-либо событие. Для записи фрагмента алгоритма перед ним открывается окно с каркасом соответствующей процедуры, где курсор услужливо подмигивает в свободном пока промежутке между begin и end.

      7.2.1. Пункт меню. В Delphi разобранная выше задача дополнения меню новым пунктом решается существенно технологичнее. (Разумеется, возможности визуального программирования давно уже появились и в Borland C++, но рассказанная в предыдущем разделе история происходила в 1995 году, когда их там еще не было.) Программист, манипулируя мышью, в стиле визуального программирования расширяет меню в нужном месте. В результате на экране появляется таблица атрибутов вновь созданного пункта, куда он может записывать нужные ему значения, например, название пункта («О программе») и т. д. Таблица эта по структуре отчасти напоминает многосвязный модуль из предыдущего раздела. Затем, как уже упоминалось, программист вводит в заготовленный Delphi каркас программный фрагмент, реализующий действия, обслуживающие обращение пользователя к данному пункту.
      Нарисованная идиллическая картинка программирования в Delphi при более внимательном рассмотрении несколько тускнеет. Увлеченность визуальной стороной привела к тому, что если раньше программист мог работать только в последовательности «запрограммировал — увидел», то теперь — только «нарисовал (увидел) — запрограммировал».
      Например, ничего не стоит, указав на какой-либо визуализируемый объект, получить доступ к любому аспекту его реализации. Более того, помимо исходного текста алгоритма перед разработчиком всегда находится таблица с атрибутами указанного объекта. Но если предпринять путешествие по тексту программы и дойти таким образом до реализации другого объекта, то таблица с атрибутами так и останется прежней, и при возврате в режим визуализации панели новый объект не станет текущим.
      В то же время, раз уж тексту программы отведена такая откровенно вторичная роль, можно было ожидать, что создатели Delphi решительно возьмут на себя заботы по поддержанию целостности пары «визуальный образ объекта — его программная реализация». К сожалению, эта целостность легко может быть нарушена при любом неверном редактирующем движении программиста. Каркас программы, изготавливаемый Delphi для ввода программных фрагментов, служит опорой лишь в первый момент — затем вводимый в гнезда каркаса текст неразличимо сливается с текстом Delphi и программист с равным успехом может удалять и изменять как свои писания, так и любые конструкции, возведенные Delphi для программного отображения визуализируемых объектов. Последствия удаления или изменения таких конструкций не всегда предсказуемы и в большинстве случаев весьма неприятны.
      Отсутствие какой-либо границы между текстом, генерируемым Delphi, и текстом, вводимым программистом, до такой степени мешает работать, что одно из руководств [Дантеман, 1995] даже рекомендует пользователю Delphi набирать служебные слова Паскаля прописными буквами (BEGIN), чтобы отличать их от окружающих служебных слов, принадлежащих каркасу и записанных строчными буквами (begin). Что же помешало авторам Delphi, бесстрашно совершившим мощный прыжок в малоисследованную в то время сферу визуального программирования, дополнить Паскаль относительно несложной конструкцией каркаса? Не исключено, что причина кроется в до обидного слабой теоретической базе и в отсутствии опыта широкого применения такого рода конструкций. Ведь если быть последовательным, то легализация каркаса закономерно приведет к внедрению в язык чего-то подобного наборным гнездам, а применяемая там ассоциативная выборка из базы данных проекта пока еще воспринимается как эксцентричная выходка, непозволительная для разработчика повседневного программистского инструментария.
      Таким образом, погрузив в среду Delphi нашу задачу о подключении пункта меню, мы заметно продвинулись вперед, однако и здесь кое-что имеет смысл усовершенствовать. С одной стороны, решение задачи радикально улучшилось: сократилось число разбросанных по тексту программы фрагментов реализации пункта и, кроме того, фрагменты оказались связанными (правда, только в одном направлении), поскольку от визуального представления пункта теперь можно перейти к таблице его атрибутов и далее к текстам фрагментов. С другой стороны, для упорядочения программного представления фрагментов вновь потребовался некоторый аналог гнезд каркаса.

      7.2.2. Программа расчета платежей. В то же время описанные выше средства Delphi охватывают только ограниченный круг визуализируемых примитивов и их модификаций. Все остальные части программы пишутся по-прежнему, и там задача обслуживания двумерных структур остается столь же актуальной. Убедительную иллюстрацию последнего утверждения автор обнаружил в первом же прочитанном руководстве по Delphi [Дантеман, 1995].
      В этом руководстве подробнейшим образом разбирается программа расчета платежей по займу. Пользователь программы задает несколько параметров займа, по которым вычисляется и выводится на экран таблица предстоящих платежей погашения. В таблице каждый платеж характеризуют многочисленные атрибуты: номер платежа; основной капитал, оплачиваемый этим платежом; проценты на капитал, оплачиваемые этим платежом; сколько основного капитала уже оплачено; остаток займа после этого платежа и т. д.
      Видно, что авторы руководства — три крепких профессионала — не один год работали над своей программой, стремясь превратить ее в образец для подражания. Программа действительно получилась неплохой. Она расчленена на два модуля. Один из них занят внешней стороной дела и заразительно энергично использует средства визуального программирования. Второму модулю поручена вычислительная работа, и он успешно с ней справляется.

      7.2.3. Добавление атрибута платежа. Все обстоит вполне благополучно до того момента, пока нам не понадобится добавить новый (или удалить существующий) атрибут платежа. Тут выясняется, что реализация атрибута распадается на восемь (!) отстоящих друг от друга фрагментов, свободно разбросанных по текстам обоих модулей.
      Участок программы, содержащий первые две точки сбора фрагментов реализации атрибута платежа, имеет вид:

TPayment =
    CLASS(TObject)  { one element in the amortization table }
          PaymentNum    
          PayPrincipal    
          PayInterest    
          PrincipalSoFar    
          InterestSoFar    
          ExtraPrincipal    
          Balance    
: Integer;
: Real;
: Real;
: Real;
: Real;
: Real;
: Real;
          PROCEDURE  GetStringForm(VAR
                    StrPayNum,
                    StrPayPrin,
                    StrPayInt,
                    StrPrinSoFar,
                    StrIntSoFar,
                    StrExtraPrin,
                    StrBalance : String15);
END;

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

Далее

Рейтинг@Mail.ru