OberonCore
https://forum.oberoncore.ru/

Модули и классы
https://forum.oberoncore.ru/viewtopic.php?f=6&t=72
Страница 1 из 1

Автор:  Илья Ермаков [ Четверг, 15 Декабрь, 2005 14:32 ]
Заголовок сообщения:  Модули и классы

На форуме Королевства Дельфи Руслан Богатырев очень хорошо выступил со сравнением концепций модуля и класса, оценкой подхода Б. Мейера к их полному отождествлению, и т.п.:
http://www.delphikingdom.com/asp/talkto ... t=10&pNo=1

Рекомендую почитать.

Свое мнение на эту тему уже высказывал в соседней ветке:
Цитата:
Почему в Java единственной единицей инкапсуляции является класс? Класс - это абстракция из предметной области. А техническое средство для формирования связанного набора из функций, типов, переменных и т.п., с сокрытием некоторых из них - это модуль. Когда пытаются обойтись без модулей и переложить соответствующие обязанности на классы, получается изврат.
Мое мнение - что модули и типы - сущности разные. А разные концепции должны выглядеть и использоваться по-разному. Лучше, когда "суп отдельно, мухи отдельно" При этом это должно закладываться в самой идеологии языка, дабы не было путаницы в головах и необходимости разбираться в наворотах излишне "творческих" писателей программ.

Идея использовать классы вместо модулей мне напоминает знаете что? Когда люди, плохо понимающие ООП, начинают использовать вместо агрегации наследование. Ну раз есть, механизм, то, типа, почему бы не использовать? Аналогично: ну раз можно в классе инкапсулировать типы и процедуры класса, то почему бы не запихать их туда?

Кстати, в ETH (Цюрихском технологическом) идет сейчас борьба между Обероном, который является там стандартным с 1989 года, и Eiffel, который продвигает Мейер.

У Мейера подход к подготовке программистов очень оригинальный: в самом начале предоставлять новичку огромные билиотеки из "черных ящиков" и учить просто их совмещать между собой, как конструктор. Потом понемногу эти "черные ящики" вскрываются, и где-то через год доходят до изучения алгоритмики, то есть, "программирования в малом". Бывает "кидание контролов на форму", а тут "кидание вызовов библиотек".

Автор:  Андрей [ Четверг, 23 Февраль, 2006 23:27 ]
Заголовок сообщения: 

В чем основная задача ООП? На мой взгляд - облегчить сопровождение программы. И такие вещи как наследование, полиморфизм и инкапсуляция действительно помогают в этом. Потому что в верно спроектированную ОО-систему всегда не трудно добавить функциональность или внести какие-нибудь другие изменения. Кто-то говорил, что ООП возможно не только на ОО языках. Возможно... но я слабо представляю себе полиморфизм на языке C (Ручное создание таблицы виртуальных функций?!). ОО языки облегчают сам процесс ООП. Основное понятие ООП - объект. (Вернее даже "субъект"). Мы знаем ЧТО он делает , но нам совсем не обязательно знать КАК он делает, если конечно он делает то, что мы от него ожидаем, не больше и не меньше :D
Например, легковой автомобиль. Мы знаем для чего он предназначен, как им управлять, какое топливо покупать, у нас есть даже права, но при этом мы можем и не знать, какие процессы происходят внутри автомобиля. Также не секрет, что автомобиль содержит в себе множество различных деталей, каждая из которых также может состоять из других деталей. Кроме того, детали нашего легкового автомобиля врядли подойдут другим объектам, например нашей стиральной машине или холодильнику. А теперь представим, что мы конструкторы автомобиля...
Прежде чем создать автомобиль нам нужно создать детали, из которых он состоит. И вот тут возникают вопросы... Понятно, что некоторые детали мы можем взять уже готовыми. Если говорить терминами КП - из других модулей. Но некоторые придется делать самим (должен же наш автомобиль чем-то отличаться от других!) Куда разместить эти наши детали? Опять же, если говорить о КП, то тут такие варианты:
1) для каждой детали создаем свой модуль.
2) все детали помещаем в тот же модуль, где находится автомобиль.
В КП второй подход, на мой взгляд, совершенно противоречит ООП, так как детали в автомобиле взаимодействуют между собой. А объекты внутри модуля могут получать доступ к полям друг друга, скорее всего невидимым вне модуля. А детали могут быть совершенно разными. И что произойдет, когда нам придет в голову поменять какую-нибудь деталь?! Конечно, детали внутри модуля могут быть связаны друг с другом только через свои интерфейсы. Они и должны быть связаны друг с другом только через свои интерфейсы!
ООП - фактически ограничение самого себя с помощью компилятора :D А если ограничений нет, то нет и ООП (программирования, проектирование есть). Получается, нам нужно каждую деталь хранить в отдельном модуле. А отдельный модуль с одним экспортируемым типом в КП, чем не класс в С++?
Можно также поместить все схожие по назначению детали в один модуль. Эти детали уж точно никак не будут взаимодействовать между собой (Карбюратор и инжектор внутри одного автомобиля не уживаются :D) Но где гарантия? То есть в этом плане КП ограничивает свободу - правильных решений не много.
Мне кажется, отсутствие инкапсуляции внутри модуля в КП, то есть отсутствие понятия КЛАСС - недостаток КП. Такой же, как отсутствие понятия МОДУЛЬ в С++. Чем плохо, если бы RECORD в КП аналогично CLASS или SCRUCT в С++ имел бы директивы PRIVATE и PUBLIC, действующие внутри модуля тоже?
[/b]

Автор:  Илья Ермаков [ Пятница, 24 Февраль, 2006 00:57 ]
Заголовок сообщения: 

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

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

А теперь представьте другой подход - мы точно также выделяем набор объектов из нашей предметной области, я называю их абстракциями. Затем мы описываем абстракции типами данных нашей программы - поля, методы, все как положено. Но, приступая к реализации, мы не будем делать из этих объектов автономных "роботов", а возьмем другой подход - "кукольный театр". Под каждую группу связанных между собой абстракций-типов-классов (назовите как угодно) выделим общего кукловода - модуль. И вот он-то и станет структурной единицей нашей программной системы. Т.е. структура нашей программной системы не обязательно совпадает (а чаще всего - не совпадает) со структурой той системы, которую мы моделируем. На практике чаще всего происходит именно так.

А при вашем подходе мы дойдем до абсурда. Вот конкретный пример, прямо из ББ (модуль Dialog). Создаем набор типов для работы с деревом: Tree - само дерево, TreeNode - вершина дерева. Пользователь не имеет никакого понятия о реализации этих типов, для него создается набор общих методов. Теперь приступаем к реализации - и сразу же видим, что эти два типа должны иметь полный доступ к внутренностям друг друга. Если заставить их взаимодействовать между собой через тот же интерфейс, который мы описали для пользователя, мы получим красивую, но крайне медленную и бесполезную реализацию. А теперь представьте, что мы пишем не дерево, а операционную систему. Такие группы объектов, которые работают вместе, будут встречаться сплошь и рядом. Что будем делать тогда?
Оказывается, что у каждого объекта есть две стороны - одной он обращен к пользователю, а другой - к тому узлу, в составе которого он работает. И директивы friend в С++ являются очень корявым решением этой проблемы, практически костылем, поэтому основным советом является "используйте friend, только если вы абсолютно уверены, что это нужно". Напротив, модульность в сочетании с ООП - элегантное и системное решение проблемы. ООП помогает нам анализировать предметную область и проектировать нашу систему, модульность помогает нам ее успешно и эффективно реализовывать.

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

Вышеописанная проблема, кстати, эта одна из причин, почему С++ не особенно жалуют системщики. Торвальдс и Танненбаум очень критически выссказывались по поводу использования С++ при написании ОС. Linux, QNX, ядро Windows - все это написано на голом С. Потому что если ваш с Мейером подход может себя оправдать при создании прикладных систем, то в системном программировании он безусловно пасует - либо реализация получается очень неэффективной, либо приходится постоянно обходить инкапсуляцию.

Оберон же как раз в первую очередь использовался как язык системного программирования (для прикладных задач он еще только начинает использоваться) - на нем оказалось очень удобно реализовывать операционные системы. И две промышленные системы жесткого реального времени (JBed и XOberon) тому доказательство, не считая исследовательских Oberon-1, Oberon System 3, Blue Bottle. Именно Оберон позволил использовать для ОС ООП без потери эффективности (кстати, и сборку мусора тоже).

Если хотите понять идеологию модульных языков - почитайте материалы в разделе Статьи у нас на сайте - там как раз эта тематика освещается.

Автор:  Vlad [ Пятница, 24 Февраль, 2006 03:28 ]
Заголовок сообщения: 

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


Эта проблема в С++ может быть решена и без friend'ов. Просто пользователь видит только интерфейсы, а реализация (модуль в терминах С++) и внутренности.

Автор:  Илья Ермаков [ Пятница, 24 Февраль, 2006 18:56 ]
Заголовок сообщения: 

Можно, не спорю.

Автор:  Сергей Губанов [ Воскресенье, 26 Февраль, 2006 11:40 ]
Заголовок сообщения: 

Андрей писал(а):
...


Какая у Вас жуткая каша в голове... :shock:

Автор:  Андрей [ Воскресенье, 26 Февраль, 2006 12:09 ]
Заголовок сообщения: 

Сергей Губанов писал(а):
Андрей писал(а):
...


Какая у Вас жуткая каша в голове... :shock:

Перед Вами типичный самоучка, да еще с довольно маленьким опытом

Автор:  Илья Ермаков [ Воскресенье, 26 Февраль, 2006 14:23 ]
Заголовок сообщения: 

Ничего, самоучками были почти все, а опыт - дело наживное :-)

Автор:  Сергей Оборотов [ Вторник, 28 Февраль, 2006 00:09 ]
Заголовок сообщения: 

Если есть желание менять детали впоследствии - то оформляйте их отдельным модулем. Кстати, очень мало программ страдает от излишней модульности.

Автор:  Клоп Говорун [ Вторник, 20 Май, 2008 00:39 ]
Заголовок сообщения:  Re: Модули и классы

Запоздалый коментарий:
Вот В. Лось тоже обещал мне качественный скачек в понимании ООП.:) И надо сказать он произошел. Перелопатил я кучу литературы по ООП и вот что я понял : лохи и лохи для лохов
это ООП. Там на самом деле никакой общепринятой точки зрения нет. Есть распростаненные мифы и куча бреда в виде например переписанных в т.н. ООП-стиле стандартных приемов программирования известных еще как "паттерны пректирования" или т.н. ОРМ (для баз данных. К смеху сказать но когдато в одой из контор директор поставил перед нами (я и мой дружок) настрочить на Firebird эволюционную БД с объектным интерфейсом. Так вот большая часть идей заложенных в ОРМ ясна была любому идиоту до появления всех этих теорий.Читая книжки по этому вопросу умиляешься до слез :)). Вообщем бред и бред.... :) :) :)

Автор:  Info21 [ Вторник, 20 Май, 2008 11:56 ]
Заголовок сообщения:  Re:

GUEST писал(а):
... очень мало программ страдает от излишней модульности.

Удачно сформулировано.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/