Объектно-ориентированное мышление
 
Автор: © Jason Steffler
Перевод: © Иван Песин .


Предисловие


   Те, кто не читал моих предыдущих статей, обязательно прочитайте statement of purpose (В вольном переводе: "Для чего это нужно" - Прим. пер.).  В этом месяце, мы будем обсуждать объектно-ориентированное мышление.  Для тех, кто хочет видеть все серии и информацию о будущих статьях, посмотрите сюда.  Для тех, кто ищет хорошие ресурсы о Squeak, вот несколько хороших.
    Это последняя из запланированных статей в cерии. Интерес читателя был достаточно высок для меня что бы продолжать эту серию, но, к сожалению, свободное время у меня исчезло :-( потому как моя жена хочет, что бы я проводил свободное время с ней :-)  Так что это будет последняя регулярная статья, по крайней мере пока что.

Цитата дня

Reason never changed a man's opinion which by reason he never acquired.
       
-- Mark Twain

Oбъектно-ориентированное мышление

    Если вы только-только пришли в объектно-ориентированное (OO) программирование, ты вскоре вы поймете, что для успешного решения проблем и задач, вам придется изменять свой стиль мышления. В этом месяце мы обсудим некоторые вещи, которые полезно помнить при работе с ОО языками программирования.

Конец линейного мышления

    По моим наблюдениям -- это первое препятствие, о которое спотыкается множество людей. Они привыкли к программам, содержащим, некоторого рода, функцию main(), и когда они попадают в Smalltalk, их пугает отсутствие линейного начала, середины и конца чего-либо. Важно понять, что Smalltalk работает с группами сотрудничающих между собой объектов. Вам лишь нужна входная точка к вашей программе. Это как будто вы открываете окно, в котором, в свою очередь, вы редактируете свое изображение, например.
   Осмысление проблемы при помощи глаголов и имен существительных (действий и объектов) -- это более свойственный нам метод мышления и часто ведет к абсолютно другому функциональному решению некоторой задачи. Попробуйте определить, какие объекты вовлечены в проблему, какие объекты нужны для помощи и какие основные свойства должны быть им присущи.
   Это приведет нас к следующей мысли:  OO программирование хорошо приспособлено к итерационным разработкам. Нам это вполне привычно: определить основные объекты, создать основные отношения и обязательства. Если вы обнаруживаете, что что-то не помещается в схему, то просто перемещаете ответственность на другой объект. Со временем ваши объекты и их ответственности конкретизируются.
   Пробуйте использовать короткие методы для того, что бы увеличить универсальность. Если вы обнаруживаете, что пишите 100 методов, значит, вы все еще мыслите линейно. Среднее число методов на объект варьируется от программиста к программисту, но все-таки оно находится около 8-10 методов. Конечно же в любом правиле существуют исключения, это просто усредненное значение.

Выбор решений и команды

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

  • если А, то Б, иначе В
    • Если данные целые, а пользовательский ввод с плавающей точкой, то взять целую часть и прибавить к данным
  • для i от 1 до максЗначение выполнять Что-то и, если необходим останов цикла, выйти из цикла
  • 1 + 2 * 3 = ?
    • Этот пример использует понятие старшинства операций, существующее в большинстве языков. Он обрабатывается следующим образом: (1 + (2 * 3)) = 7.  Но для того, что бы выяснить, как обработать выражения, язык должен сделать выбор(найти решение), какой оператор выполнять первым.

    Основной проблемой такого стиля программирования является то, что вам приходится выполнять однотипные выборы в разных частях программы. Когда ваши требования меняются, приходится изменять условия в разных местах программы.
    В OOП обычно применяются команды. Вы приказываете объекту выполнить то, или иное действие. Если объект этого делать не должен, или должен делать как-то иначе, он сам будет знать об этом. А так как вы просите сделать что-либо объект, то, соответственно, не надо выбирать решение. Вы поступаете следующим образом:

  • объект сделайЭто
    • Например, не имеет значения, что вы складываете целое и дробное числа. Дробное знает как прибавлять к себе дробное, и как - целое.
  • аКоллекция сделай: [:каждыйЭлемент | каждыйЭлемент делайЧто-то]
    • Обратите внимание, что вы не выполняете никаких проверок границ - коллекция сама знает, что и как делать
  • 1 + 2 * 3 = ?
    • В этом примере, нужно помнить, что в Smalltalk уцелые числа - тоже объекты. Та, что мы просим объект 1 добавиться к объекту 2, после чего результат умножиться на объект 3. Откуда следует, что обработка выполняется, как: ((1 + 2) * 3) = 9.

Не волнуйтесь о деталях

   Однажды я слышал, что Алан Найт (Alan Knight) отметил, люди берутся изучать Smalltalk, если на их вопрос:  "Как работает Transcript : 'HELLO WORLD'", ответить: "Меня это не волнует".  Извечная тема для новичков в Smalltalk - это четко знать, как что работает, вплоть до всех методов шаг за шагом вызываемых вплоть до последней библиотеки. Это связано с линейным мышлением, при котором вам нужно знать и понимать, как происходит выполнение программы. Если вы обнаруживаете, что вы копаетесь в деталях классов, то, вероятно, вы продолжаете думать линейно.
    С этим хорошо соотносится то, что Smalltalk удобен для кодирования сверху-вниз. Откладывайте реальную работу и принятие решений так далеко, насколько получается-- создавайте "заглушки" и абстрактные обязанности, если только возможно. Определение работающей системы (пусть даже тривиальной) даст вам ощущение могущества, и она не перестанет работать на всех этапах добавления в нее "плоти". Вы будете иметь работоспособную систему почти на всех этапах разработки

Упрощение инкапсуляцией

    Пробуйте группировать данные вместе с соответствующими операциями в объект. Если вы работаете напрямую с данными объекта -- вы нарушаете инкапсуляцию. Если вы выполняете что-то вроде: Объект аАтрибут аЧастьАттрибута делайЭто, вы нарушаете инкапсуляцию.
    Хорошим примером инкапсуляции может служить приведенный выше цикл. Коллекция знает, сколько у нее есть элементов, и проводит операцию для каждого из них. Вас же абсолютно не волнует, сколько их там.

Повторное применение

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

...через библиотеку классов

    Перед тем как писать что-либо, стоить глянуть в библиотеку классов -- быть может это уже сделал кто-то за вас. Изобретение колеса определенно не объекто-ориентировано и просто пустая трата времени.
    Другое важное правило при изучении Smalltalk -- это пропорция между временем, которой вы проводите, исследуя библиотеку классов, и временем, потраченным непосредственно на программирование. С увеличением опыта, пропорция будет изменяться, но пока вы новичок, будьте готовы к тому, что вы будете проводить больше времени в просмотре библиотеки..
    Тут можно вспомнить замечание (к сожалению, не момню чье), сделанное во время "могучего флейма" по поводу Числа Строк Написанного Кода [Lines Of Code -- LOC]. Было сказано, что программисты на Smalltalk должны измеряться числом ненаписанных строк кода, поскольку это экономит время и затраты на сопровождения за счет повторного использования библиотеки классов.

...с помощью дополнительного кода

    Smalltalk имеет богатую историю и большую пользовательскую аудиторию.  Так что весьма вероятно, что существует свободный или открытый код, необходимый вам. Просматривайте сайт UIUC repository, ищите в веб и спрашивайте в группах новостей.

...с помощью ответственностей

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

...при помощи наследования

    Наконец мы добрались до наследования. Я оставил это напоследок, потому как (по моему мнению) чересчур разрекламировано и люди нередко злоупотребляют чрезмерно глубоким наследованием в классах.
    Например, если вы пишите систему для больницы или госпиталя, вы, наверное, захотите наследовать характеристики объекта Личность, такие как Фамилия, Имя, и номерСтраховки, создавая подклассы Доктор и Пациент.

Распределение ответственностей

    Наблюдайте за разрастанием вашей системы -- вы можете это увидеть, если нарисуете диаграмму вашей программы, а у вас получится тысяченожка. Это значит, что у вас слишком много ответственностей на объект. Вам следует попробовать как-нибудь перегруппировать объекты.
    Другой знак -- это использование объекта 'manager'.  И снова же, бывают случаи, когда использование объекта manager совершенно логично и оправдано. Потому достаточно трудно установить злоупотребляете ли вы объектом manager. Я предпочитаю использовать правило, которое я слышал от Алана Найта: объект manager должен быть как настоящий менеджер: он не должен делать никакое работы -- только управлять.

Мелодичный Squeak

(Игра слов: Squeak - "скрип" и название программы. - Прим. пер.)

В этом месяце вышел релиз Squeak 3.0! :-)  Чтобы быть как можно более полным, в описании я исхожу из предположения, что вы хотели бы запускать Squeak в Windoze и Linux. Для такой установки вам потребуются права пользователя root.  

Шаг 1:  Загрузка Squeak 3.0

С FTP сайта ftp://st.cs.uiuc.edu/pub/Smalltalk/Squeak/3.0 загрузите:
  • Squeak3.0-win.zip, включающий:
    • Squeak.exe, виртуальную машину (только для Windoze, для linux надо компилировать)
    • Squeak3.0.image, (подходит как для linux, так и для Windoze)
    • SqueakV3.sources, (подходит как для linux, так и для Windoze)
  • Squeak-3.0pre2.tar.gz
    • Исходный код для компиляции виртуальной машины для linux

Шаг 2: Установка в каталог запуска

Я пологаю, что точка монтирования вашего Windoze суть /windoze.

Примечание:  если вы не хотите/не имеете в вашей системе двойной загрузки, можете изменить установочный путь так, как вам удобно, например: ~myuserid/squeak3, после чего удалите следующие файлы: NPSqueak.dll, Squeak.exe, SqueakFFIPrims.dll.

  • Создайте каталог /windoze/squeak3
  • Разархивируйте файл Squeak3.1-win.zip в каталог /windoze/squeak3.

Шаг 3: Установка виртуальной машины для linux

Все это действительно очень просто -- даже если вы никогда и ничего в своей жизни не прораммировали и не компилировали. Вот необходимые шаги:

  1. Разархивируйте Squeak-3.0pre2.tar.gz куда вам нужно (разархивируйте с подкаталогами, это извлечет Squeak-3.0 в отдельный каталог)
  2. cd в каталог с разархивированными файлами.  (Файл BUILD.UnixSqueak содержит то, что вы сейчас читаете)
  3. mkdir build
  4. cd build
  5. ../src/unix/configure --bindir="/windoze/squeak3"
  6. make
  7. make install  (Примечание: на этом шаге важно иметь привилегии пользователя root, потому как по умолчанию, пакет ставится в каталоги /usr/lib, /usr/man, и т.д.)
    1. Тут вы получите несколько сообщений об ошибках (если только вы не ставите на файловую систему Linux), так как файловая система Windoze не поддерживает связи
    2. Выполните следующие команды:
    3. cp /usr/lib/squeak/3.0/squeak /windoze/squeak3
    4. cp /usr/lib/squeak/3.0/inisqueak /windoze/squeak3

Шаг 4: Запуск Squeak :-)

  • cd /windoze/squeak3
  • squeak Squeak3.0final.image

...Запуск Squeak под управлением Windoze, оставляется читателю, как упражнение  ;-)

Обзор

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

Основной экран.  Логотип Squeak в верхнем правом углу - это клон программы xeyes, когда глаза следят за мышью.
    

Если навести курсор на логотип, то окажется что есть всплывающая подсказка.
    

Если вы кликните на проекте в нижнем правом углу, он развернется на полный экран.
    

И, наконец, давайте кликнем на музыкальном проекте.
    

Взгляд вперед

    Увы! Сейчас не будет никаких планов на будущее, из-за моих трудностей со временем. В следующих сериях я планировал описать некоторые основы программирования, например: проверка юнитов (SUnit), управление исходным кодом (изменяемые наборы и SCAN), тур по часто употребляемым объектам, управляющим структурам и Squeaklets.

    Тем временем, я бы настоятельно рекомендовал загрузить Squeak 3.0 и попробовать дополнительный код STP, для первого знакомства.  Он доступен с  http://www.create.ucsb.edu/squeak/STP12.html

    Я наслаждался, изучая Squeak в течение нескольких месяцев, надеюсь, вы тоже получите удовольствие.


Код Smalltalk

Кто-то сообщил мне, что ScopedBrowser, который я использовал в статье 4 некорректно работает в Squeak v3.0, так вот обновленная версия.
Примечание: Я заметил, что SUnit теперь включается в основной пакет, так что я включил некоторые тесты юнитов.  После загрузки кода, если вы хотите запустить тесты, выполните: TestModel openAsMorph, после чего нажмите кнопку Run. Вы заметите 8 окошек, которые всплывут и закроются. И не должно быть никаких ошибок.


Copyright © 2001, Jason Steffler.
Copying license http://www.linuxgazette.com/copying.html
Published in Issue 65 of Linux Gazette, April 2001

Вернуться на главную страницу