Философия программирования Win95. Введение

Отсканированная мной книга Лу Гринзоу "Философия программирования Windows 95/NT".  Пока выкладываю введение. Обсуждение, исправление опечаток и вопросы - в комментариях.



  
You use your creative talents to transform a business environment.

Предсказание, которое я получил в китайском ресторане в
день подписания контракта о создании этой книги

Forward, forward let us range,
Let the world spin for ever down the ringing grooves
of change.

Альфред, Лорд Теннисон

Введение

Я не верю в пирожки с предсказаниями (как, впрочем, и в остальную, очень
модную сегодня метафизику), но вышеприведенный «прогноз» весьма удачно
перекликается с теми целями, которые я преследовал при написании этой кни-
ги: изменить у большинства из вас образ мышления о ваших пользователях и
о программировании для Windows 95, усовершенствовать методы, которые вы
используете в ремесле программирования. При этом я уже высказал одно раз-
машистое предположение (на самом деле, их сделано несколько, но давайте для
начала ограничимся одним, наиболее очевидным и существенным): програм-
мирование не является ни искусством, ни наукой, но оно явно несет в себе
признаки и того, и другого; и вместе с остальными чертами это делает програм-
мирование именно ремеслом. Я думаю, что этот факт имеет важный, даже глу-
бинный смысл для всех программистов, особенно сейчас - во время бурного
развития мира Windows.

Благодаря появлению Windows 95, взрывному расширению рынка домаш-
них компьютеров, унылой картине качества коммерческого программного
обеспечения в целом, а также возросшей популярности операционных систем
Windows NT и OS/2 Warp, окружающий нас компьютерный мир буквально из-
менил свой облик в течение последнего года. Когда происходит нечто подобное,
у вас есть выбор из двух путей: продолжать старую игру и смотреть на за-
тухающее вращение рулетки, или впрячься в работу по адаптации себя к этому
миру. Я предпочитаю последнюю стратегию, и, если вы уже смогли выжить в
этой игре, я подозреваю, вам она также больше подходит.

Что такое «программирование»?

Как вы увидите в этой книге, я постоянно (и, надеюсь, убедительно)
утверждаю следующее: чтобы быть отличным программистом, вы должны все-
гда стараться окинуть как можно более широким и внимательным взглядом
стоящие перед вами проблемы, а затем стремиться к сбалансированному
решению. Лишь немногие профессии подвержены опасности «не видеть леса
 за деревьями» в такой же степени, как программирование. Поэтому для вас жиз-
ненно важно научиться глядеть на вашу задачу «с высоты 30 000 футов».

Ладно, хватит увиливать от основной темы разговора. Что же такое
программирование? Программирование - это ремесло использования раз-
нообразного инструментария (аппаратного обеспечения, программ, исследова-
тельских материалов, вашего собственного опыта и т. д.) в создании уровней
абстракции и применении их для решения логических задач. Эти уровни
абстракции позволяют вам сконструировать послойную иерархию архитектур
или виртуальных машин, которые в конечном счете и работают совместно,
решая поставленные задачи.

Хмм... Звучит так, как будто мы уже вышли в открытое море, в то время
как на самом деле едва оттолкнулись от причала. В качестве примера этого на-
слоения виртуальных машин, давайте рассмотрим, как вы обращаетесь с мате-
матическими операциями в ваших программах. Когда вы пишете операторы
С++, совершающие простые вычисления с вещественными числами, у вас уже
есть некоторый набор предположений о том, как будут работать соответ-
ствующие подпрограммы стандартной библиотеки компилятора, как они будут
обрабатывать переполнение, деление на ноль, другие общие ошибки. Но что
если компьютер, на котором работает ваша программа, не имеет сопроцессора?
Программисты уже так давно привыкли к идее надежной поддержки эмуляции
вещественных вычислений, что вряд ли уже задумываются над этим вопросом;
такая поддержка - это просто еще одна данность, часть пейзажа, она работает
так, как и должна работать. И точка.

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

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

Если вы хотите другой пример, задумайтесь о работе в Windows и состав-
лении SQL-запроса к реляционной базе данных. Между строкой «SELECT *
FROM CUSTOMERS» и набором нулей и единиц, закодированных на
вращающейся тарелке диска, так много всего происходит! Опять же, все это -
уровни абстракции и виртуальные машины. (Я бы с удовольствием когда-ни-
будь взялся обучать студентов компьютерной архитектуре, и тогда вынес бы на
заключительный экзамен только один вопрос: перечислите детально все уровни
архитектуры и интерфейса, задействованные в этом примере. Правда, я по-
дозреваю, что студенты вряд ли получат столько же удовольствия от такого
эксперимента, сколько получу я.)

Такая работа с уровнями абстракции и конструирование своих собственных
виртуальных машин означают, что вся ваша программистская деятельность на-
сквозь пронизана многочисленными предположениями. Подкопайтесь дос-
таточно глубоко под эти предположения, и вы достигнете сути, вашей филосо-
фии программирования. Это влияет и накладывает отпечаток на все, что вы
делаете как программист, независимо от того, понимаете вы это или нет. Ваша
философия формируется вашим опытом и образованием, а зачастую - ве-
щами, вовсе не имеющими непосредственного отношения к программированию,
такими, как ваш возраст, например. (Если вам кажется, что ваша одежда и
прическа на фотографиях 15- или 20-летней давности выглядят забавно,
попробуйте посмотреть на ваш же собственный код, написанный не так уж
давно. Это будет почти то же самое, что смотреть шестнадцатеричную версию
«The Brady Bunch». [название телевизионного шоу на семейные темы, чрезвычайно
популярного в 70-х годах в США (по мотивам этого шоу был снят целый ряд фильмов и
сериалов])

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

Мой подход

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

В Эта книга будет больше говорить о том, чего вам не следует делать,
чем о том, что следует. Например, я буду часто упоминать многочис-
ленные «программистские байки», которые все мы рассказываем друг
другу для оправдания своих программерских трюков и стиля. Заметь-
те, что при этом я вовсе не претендую на собственную непорочность; я
скажу сейчас и буду говорить потом, что я сам совершал те грехи, ко-
торые будут многократно упоминаться в этой книге, и рубцы на моих
программах - тому доказательство. Я был удачлив и не один раз по-
падал в программистскую аналогию той житейской ситуации, когда
просыпаешься утром в жестоком похмелье, абсолютно не помнишь о
том, как добрался домой прошлой ночью, и обнаруживаешь, что твой
автомобиль припаркован на газоне с распахнутой дверью. (И если вы
хоть на наносекунду подумали, что данная аналогия как-то оправды-
вает такое поведение, то вы не уловили моего едкого сарказма.)

В Мне часто придется полагаться на то, что вы будете самостоятельно су-
дить о том, как применять тот или иной мой совет. Как бы все мы ни
желали обратного, современное программирование очень редко ставит
«бинарные» проблемы; почти каждая задача, с которой вы столкнетесь
(а всякая интересная задача - наверняка) будет иметь решение как
раз в той самой безбрежной, пасмурной серой зоне между черным и
белым. Когда я говорю «будьте рассудительны», - это не просто де-
журная фраза, заменяющая более конкретные рекомендации; эти сло-
ва означают, что правильный ответ сильно зависит от вашей конкрет-
ной ситуации, и что с моей стороны было бы безответственно высказы-
вать более определенное предложение. Многие решения вообще
просто-напросто зависят от контекста. Какие инструменты вы исполь-
зуете? Какие ограничения накладываются временем, вашей админи-
страцией, вашими пользователями? Какова ваша квалификация? И
даже еще интереснее: то, что является правильным для вас сегодня,
может оказаться совершенно неверным для другого или для вас само-
го, но спустя несколько месяцев. Трюк заключается в том, что на
проблему нужно посмотреть через призму ваших собственных преду-
беждений (а в этой профессии их у каждого в изобилии!) и выбрать
оптимальный курс ее решения в данном проекте. Всякий раз, когда я
слышу из уст программиста фразы типа «Я был вынужден использо-
вать инструментарий X, потому что... начальство приказало / только
он был доступен / у меня не было времени изучить более подходящий»,
в моем мозге раздается тревожный сигнал. Иногда программист
прав, и у него действительно не было другого выбора, кроме этого,
очевидно, не самого оптимального. Но слишком часто программист
просто оправдывает такими словами использование любимого старого
инструмента или блестящей новой игрушки.

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

В В книге есть несколько мест, где я показываю наилучшее решение той
или иной проблемы - наилучшее из тех, которые я сам смог найти, -
и затем прошу вас самих сказать мне, нет ли еще более удачного реше-
ния, которое я не увидел. Я не претендую на обладание совершенным
знанием по тем проблемам, которые упомянуты в этой книге; почти ни
один технический писатель не мог бы честно претендовать на такое
(хотя многие все еще будут делать это, явно или неявно). Также не
следует ожидать, что мои взгляды и мнения являются окаменелостями.
Если спустя шесть месяцев или год после того, как это издание попадет
на книжные полки, вы столкнетесь со мной на конференции, или мы
обменяемся электронной почтой, вполне вероятно, что я скажу вам: «С
тех пор я приобрел новый интересный опыт, который изменил мое мне-
ние по тому или иному вопросу». Эта книга - на самом деле лишь мо-
ментальный снимок, сделанный на одном из отрезков моей персональ-
ной одиссеи в мире программирования. Мир меняется, вещи меняются,
я - тоже.

Мои предположения относительно вас

Писатели-беллетристы часто говорят о мифическом «среднем», или «ти-
пичном», читателе, которого они себе представляют, когда пишут свои
творения. Технические писатели также держат в голове некоторую модель мен-
талитета своих читателей. Поскольку мои представления о вас подсвечивают
практически каждое слово в этой книге, позвольте мне приоткрыть сундучок с
моими предположениями и дать вам заглянуть в него:

В Вам нравится программировать, и вы делаете это либо профессиональ-
но, либо как страстный любитель. Я считаю всякого, кто програм-
мирует за деньги, профессионалом, даже если его рабочая должность
не называется «программист». Одной из волнующих сторон сегодняшнего мира
Windows является то, что все больше и больше непрограм-
мистов пишут программы, на которые другие люди полагаются в
реальной работе, - к проблемам, вызванным такой ситуацией, я
обращаюсь на многих страницах этой книги.

В Вы - «фанатик качества». С одной стороны, я ненавижу все эти шут-
ки и результаты заумных научных исследований, делящие все чело-
вечество на какие-нибудь два лагеря. Но в то же время я нахожу, что
компьютерные пользователи, вообще говоря, распадаются на две кате-
гории по тому, как они относятся к ошибкам в программах. Предста-
вители одной группы просто пожимают плечами по поводу брака,
произносят «Ну, что ж, ошибки случаются...» и продолжают жить с
тем, что есть под рукой. Лично я неодобрительно отношусь к таким
пользователям. В основном, потому, что сам принадлежу ко второй
категории - к группе людей, которые могут буквально взрываться не-
годованием, когда обнаруживают ошибку или сбой в программе. Всем
моим знакомым известно, что моя ругань порой бывала весьма мно-
гоэтажной, когда я спотыкался о то, что я называю «по-настоящему
глупейшей ошибкой».

Вы без сомнения заметили, что сегодня - совсем не счастливое время
для «фанатиков качества» в компьютерной индустрии. Качество ком-
мерческого программного обеспечения в последнее время катилось
вниз по скользкому склону, порой с головокружительной быстротой.
Еще более беспокоит то, что поставщики программного обеспечения
переходят на другую модель поддержки заказчиков (в данном случае
я использую термин «поддержка» с большой натяжкой) - такую мо-
дель, при которой в лучшем случае делаются вялые усилия для выпус-
ка заплат, а зачастую все вообще сводится к тому, что заказчик платит
деньги за свою собственную работу по обнаружению ошибок и опове-
щению о них производителя. (Вероятно вы слышали такое определе-
ние, как chutzpah [это слово (на языке идиш) по значению близко к «наглый»,
 «самонадеянный»] - мальчик, который сначала убил своих родителей,
а потом сдался на милость правосудия и требовал снисходительности
к себе как к сироте. Мне кажется, что современная программная инду-
стрия рискованно приближается к тому, чтобы вот-вот заслужить такое
определение. Но я отвлекаюсь.)

В Вы заинтересованы в серьезных, долгосрочных проектах, а не только
в наспех сделанных халтурах для одноразового использования. Об
этом критичном противопоставлении, о разнице между публичными и
приватными программами я говорю в Главе 1, «Добро пожаловать в
реальный мир».

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

В Вы заинтересованы в переносимости исходных текстов, а также в со-
вместимости программ с разнообразными воплощениями Windows. Я
скажу сразу: если вы думаете, что не заинтересованы в этом, то вы,
вероятно, сами себя обманываете. По моим ожиданиям, еще долгое
время после публикации этой книги наши пользователи будут запус-
кать самые всевозможные версии Windows - от Windows 3.0 до Win-
dows NT 4.0 включительно. Эпоха наивности закончилась; старое
доброе время, когда мы могли игнорировать все эти сложности, уже
тускнеет в памяти.

В Вы обладаете достаточным опытом разработки программного обес-
печения для Windows на одном или нескольких языках програм-
мирования, таких как C/C++, Pascal или Basic. Под определением
«достаточный опыт» я имею в виду примерно 3000 строк кода, напи-
санных в течение последнего года, или 20 000 строк - в течение по-
следних пяти лет.
 

Что вы найдете в этой книге

Эта книга разделена на четыре основные части - «Основы», «Практика»,
«Великий перевал» и «Ресурсы», - плюс несколько приложений.

В части «Основы» мы поведем долгий разговор о ремесле программирова-
ния, о многих его сторонах, которые все мы порой воспринимаем неверно. Этот
раздел охватывает большое число проблем, с которыми опытные программисты
уже хорошо знакомы. Тем не менее, я призываю прочесть эту часть книги даже
тех, кто уже миллиарды раз проходил цикл редактирование/компиляция/
тестирование - многие затронутые здесь вопросы являются важными как ни-
когда, особенно в свете новых реалий нашего изменчивого мира.

В части «Практика» я демонстрирую некоторые приемы, технологии и
идиомы, которые я изобрел, открыл или позаимствовал (читайте: украл) у
друзей. Почти весь код, встречающийся здесь, отнюдь не является примером
передовых достижений. В то же время, ничто в этой части книги не содержит
каких-либо таинственных, граничащих с недозволенным, трюков типа исполь-
зования недокументированных интерфейсов или возможностей Windows.
Скорее, эти главы задумывались как демонстрация того, как при помощи ми-
нимального планирования вы можете комбинировать простые и легко сопрово-
ждаемые технологии кодирования для создания удобных и полезных программ
для Windows 95.

Часть «Великий перевал», охватывает тему, важность которой постоянно
растет, переносимость кода между различными вариациями Windows, а
также бинарная совместимость между тремя 32-разрядными платформами Win-
dows (Win32s, Windows 95 и Windows NT). До того, как на свет появились
Windows 95 и Windows NT 3.51, эти проблемы практически не существовали
для подавляющего большинства Windows-программистов. Мы писали
программы для 16-разрядной Windows и продолжали радостно шагать своим
путем, беспечно игнорируя Windows NT и довольно ограниченный и спе-
цифичный (относительно говоря) круг ее пользователей.

В заключение, в части «Ресурсы» я расскажу об инструментах и ресурсах,
которые, на мой взгляд, являются весьма и весьма полезными
программирующим для Windows. Как я говорил выше, программирование -
это ремесло, в котором вопросы практики и используемого инструментария
переплетены так тесно, как ни в одной из других профессиональных областей.
Поэтому я считаю, что любой длинный книжный разговор о программировании
бесплоден и незавершен, если он хотя бы краешком не касается проблем
выбора инструментария и обсуждения конкретных инструментов. Другими сло-
вами, теория и философия программирования безусловно являются необходи-
мыми компонентами вашего умственного багажа, но их одних совершенно не-
достаточно.

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

= Приложение A: MegaZero, самое законченное в мире, ничего не де-
лающее 32-разрядное приложение (которое призвано просто проде-
монстрировать некоторые программистские приемы, обсуждаемые в
части «Практика»).

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

= Приложение С: Библиотека Win32u - первая, зачаточная версия
вспомогательной оберточной библиотеки, которую вы можете исполь-
зовать для преодоления некоторых проблем совместимости между
Win32s, Windows 95 и Windows NT.

 

Приложенный код

Очевидно, я был вынужден выбрать для примеров только один язык, ком-
пилятор и среду разработки, в противном случае я рисковал бы вообще никогда
не закончить эту книгу. (Кстати говоря, этот выбор был похож на обычную
проблему выбора инструментария для выполнения очередного проекта.) Я
выбрал Microsoft Visual С++ 2.2 и MFC, самые последние версии этих продук-
тов, доступные во время написания этой книги. Кроме того, в книгу вошли не-
сколько примеров 16-разрядного кода, компилируемого при помощи Visual
С++ 1.52 и (о-ох!) один модуль на языке Pascal.

На сервере находятся все файлы, созданные компиляторами и их ин-
тегрированными средами разработки. Это должно позволить вам ин-
сталлировать примеры и использовать их, применяя все возможности Visual
С++. В целях экономии времени, я не озадачивал себя такими проблемами, как
удаление ненужных ресурсов из программ или создание специальных значков
для каждой программы. Я надеюсь, вы не питаете ненависти к стандартному
значку «AFX», который используется оболочкой Visual С++ по умолчанию, по-
тому что вы не раз увидите его в моих примерах.

Пожалуйста, обратите внимание на то, что решение об использовании ком-
пиляторов Microsoft было скорее отражением реалий рынка, но никак не
одобрением или поддержкой Visual С++ или MFC. Когда я начинал писать эту
книгу, будущее известной библиотеки OWL (как и будущее самой компании
Borland) выглядело очень неопределенным, в то время как MFC становилась
почти что «языком межнационального общения» в программировании для Win-
dows.

 
Чего вы не найдете в этой книге

Опять пришло время поговорить о доверии к моим рекомендациям, изло-
женным в этой книге. Совершенно определенно, эта книга не является
исчерпывающим обзором, охватывающим С++, или объектно-ориентированное
программирование (OOP), или OLE 2.0, или Win95 API, или WinG, или
любую другую специальную область. Предназначение этой книги - коснуться
Windows-программирования на уровне фундамента и философии; в связи с
этим, я буду говорить о концепциях и проблемах, общих для программирова-
ния в целом, но в то же время: особенно уместных для кодирования под Win-
dows 95.

 Нахальная вставка

Одним из наиболее поучительных и развлекательных моих занятий в
течение последних нескольких лет было создание и маркетинг условно-бесплат-
ной Windows-программы под названием Stickies!. Эта программа предостав-
ляет пользователю электронный аналог записной книжки, файловую базу дан-
ных, напоминающую шкаф с ящичками, будильник и другие многочисленные
возможности. На протяжении повествования данной книги я не раз упоминаю
те знания и навыки в области программирования и общения с незнакомыми
пользователями, которые я приобрел в процессе маркетинга программы Stick-
ies!. А также - целый ряд неожиданных проблем переносимости, с которыми
я столкнулся при работе с Windows 95.

Для патологически любопытных: программа Stickies! была впервые выпу-
щена 2 октября 1992 года, а ее следующая версия (4.0) выйдет в свет вскоре
после того, как я закончу эту книгу и недельку отосплюсь. Оценочная копия
Stickies 3.1 находится по адресу: http://www.symbol.ru/russian/library/
prof_prog/tools/stickies.


Не оставайтесь в стороне

Карьера в программировании, как и сама жизнь, - путешествие. С одной
стороны, эта книга представляет собой некую контрольную точку в моей
личной программистской одиссее, сборник избранных моих приключений,
включая и успехи, и неудачи, плюс некоторые наблюдения и рекомендации, -
взгляд на все это сквозь линзы, подкрашенные цветами Windows 95. Но с ва-
шей помощью данная книга может оказаться чем-то большим, нежели только
это. В начале этого проекта я разговаривал с Кейтом Уэйскампом, моим изда-
телем, и Роном Пронком, моим редактором, и мы сошлись на том, что эта книга
должна иметь расслабленный стиль изложения, напоминающий разговор на
встрече друзей. Поэтому я надеюсь, вы извините меня, если я скажу, что при
написании этой книги я часто представлял себе такую картину: дюжина прияте-
лей собралась во дворе моего дома прохладной летней ночью после отличного
ужина и бурного выходного дня на пляже, все развлекаются с летающими
тарелками, болтают о программировании, делятся анекдотами, шутками и ужастиками
про руководителей и даже грешат случайными «религиозными»
спорами.

Что бы вы ни делали, не будьте посторонним. Скажите мне, в чем вы
считаете меня правым, а в чем - нет, расскажите мне ваши программистские
анекдоты (чем смешнее, тем лучше, но приветствуются любые), предложите
мне, что на ваш взгляд следует (или не следует) включить в следующее издание
этой книги. Я выставлю закуски, а вы приносите прохладительное, и когда
игрушечная летающая тарелка случайно залетит во двор моих соседей, мы по-
шлем Рона и Кейта за забор, чтобы притащить ее назад.

Lou Grinzo
P.O. Box 8636
Endwell, NY 13762-8636
Compuserve: 71055,1240
Endwell, NY


Лу Гринзоу
P.O. Box 8636
Эндвелл, Нью-Йорк 13762-8636
Compuserve: 71055,1240
Эндвелл, Нью-Йорк