Оберон-технология: особенности и перспективы |
Тематика обсуждения: Оберон-технология. Особенности, перспективы, практическое применение.
Всего в теме 6256 сообщений
Добавить свое сообщение
Отслеживать это обсуждение Обсуждение из раздела Школа ОБЕРОНА
№ 2726 15-02-2007 15:38 | |
Ответ на »сообщение 2724« (Илья Ермаков)
___________________________
1) Семантика Adder такова, что Left и Right устанавливаются один раз на всю его жизнь. Тогда это делает обязательная фабричная процедура.
О точ и речь. Какая обязательная ? Кто программиста обяжет ?
Конструктор класса ? Так нет его в обероне.
Интерфейс ? Так не прописана в интерфейсах "обязанность" вызывать те или иные процедуры.
Кто помешает программисту взять да и вызвать GetSum не устанавливая Left и Right ?
2) Если Left и Right нужны только для конкретной операции над ними, то лучше и сделать их параметрами метода этой операции.
Это мой аргумент а не ваш Илья. :)) Это аргумент функциональщика в пику обьектам. Вы правы, обьекты на черта не нужны.
а) либо атрибут обязательно определен для объекта, т.е. есть инвариант на определенность поля - тогда начальное значение устанавливается фабричной процедурой, а потом меняется методами;
Вы все время говорите о какой то фабричной процедуре которую программиста ОБЯЖУТ вызвать. Но при этом эта процедура - конструктор класса. Что это за механизм обязаловки такой интересный ?
Может пример описания приведете ?
№ 2725 15-02-2007 15:02 | |
№ 2724 15-02-2007 15:00 | |
Ответ на »сообщение 2723« (Jack Of Shadows)
___________________________
Пример слишком "из пальца". Конкретно могут быть три ситуации:
1) Семантика Adder такова, что Left и Right устанавливаются один раз на всю его жизнь. Тогда это делает обязательная фабричная процедура.
2) Если Left и Right нужны только для конкретной операции над ними, то лучше и сделать их параметрами метода этой операции.
3) Если какой-то атрибут объекта меняется многократно, то, опять же, распадается на два варианта:
а) либо атрибут обязательно определен для объекта, т.е. есть инвариант на определенность поля - тогда начальное значение устанавливается фабричной процедурой, а потом меняется методами;
б) либо семантика объекта позволяет атрибуту быть неопределенным, но перед частью операций он должен быть определен - тогда вручную перед такими операциями контроллируем предусловие.
Грамотное проектирование решает все проблемы.
А грамотное проектирование в Оберонах гласит - стремиться не экспортировать конкретные типы с поведением, ВСЕГДА инкапсулировать их и создавать исключительно через фабрики. Даже если подобная строгость на момент разработки модуля не дает никаких преимуществ, она аукнется в будущем, когда система будет расширяться.
Конструкторы могут быть полезны при таком подходе оччень-оччень редко. Обычно для статических записей, размещаемых на стеке. Однако такие записи редко имеют какое-то сложное поведение, а часто - не имеют связанных процедур вообще.
А еще одно решение контроля инвариантов предлагает Зоннон - специфицировать, в каком порядке какие процедуры должны вызываться, через описание протокола взаимодействия в ЕБНФ.
№ 2723 15-02-2007 13:30 | |
Ответ на »сообщение 2722« (Илья Ермаков)
___________________________
Так инкапсуляция на что? Гарантируется, что с объектом работают только через фиксированный набор экспортированных процедур.
А как гарантировать что из этого фиксированного набора процедур ПЕРВОЙ будет вызванна какая то конкретная а не любая из них ?
Скажем пример
обьект Adder имеет три экспортированных метода SetLeft, SetRight, GetSum
Метод GetSum оперирует с полями которые были ДО его вызова инициализированны методами SetLeft и SetRight.
В java к этому набору еще добавлется конструктор Adder(Left, Right); который обязан вызываться первым.
Таким образом гарантируется что ДО вызова GetSum поля Left и Right будут инициализированны.
А как в обероне гарантировать что до вызова GetSum поля Left и Right ОБЯЗАТЕЛЬНО бelen инициализированны через соответствующие экспортированные процедуры ?
№ 2722 15-02-2007 13:20 | |
Ответ на »сообщение 2720« (Антон Григорьев)
___________________________
Так инкапсуляция на что? Гарантируется, что с объектом работают только через фиксированный набор экспортированных процедур. На входе этих процедур проверяем параметры на допустимость. Внутри модуля предполагаем, что "все свои" и инварианты блюдут, ничего проверять не надо.
По поводу NIL - он обязан инициализироваться NIL-ом в любой реализации Оберона, этого требует герметичность системы типов.
№ 2721 15-02-2007 11:45 | |
Ответ на »сообщение 2720« (Антон Григорьев)
___________________________
Про 5%. А что вы планиркете каждый раз при использовании проверять на допустимость?
Может лучше локализовать проверки в местах присвоения новых значений? Сообщение не подписано
№ 2720 15-02-2007 11:36 | |
Ответ на »сообщение 2710« (Руслан Богатырев)
___________________________
Какая-то невесёлая картина получается с этими вашими ASSERT'ами. Обязательная проверка границ массива снижает быстродействие программы в среднем на 5%. Это - простое сравнение одного числа с двумя другими. В более запутанных случаях накладных расходов будет ещё больше. Даже в приведённом вами записи на Модуле простой проверки попадания трёх чисел в соответствующие диапазоны недостаточно - 31 февраля такую проверку пройдёт. А условия целостности данных могут быть очень сложными.
Или вот такой пример. Запись на Обероне:
tPrintDesc = RECORD (Queue.tNodeDesc);
Print : PROCEDURE(node: QueueNode);
END;
(Пример взят из упоминавшейся здесь книги http://www.piter.com/book/978546900378 ). В описании языка Оберон я не нашёл упоминаний о том, что процедурные переменные по умолчанию инициализируются NIL'ом. Следовательно, сразу после создания такой записи указатель Print будет указывать неизвестно куда. Каким ASSERT'ом мы можем проверить, что он указывает на корректную процедуру, а не имеет неизвестно какое неинициализированное значение? И куда, кстати, поместить этот ASSERT? Заставлять пользователя вызывать самому вставлять ASSERT перед вызовом Print? Вряд ли ему это понравится. Другой путь - не экспортировать Print, а экспортировать процедуру, которая получает указатель на tPrintDesc, проверяет его поле Print на корректность, и только потом вызывает Print. Жуткие накладные расходы.
№ 2719 Удалено модератором | |
№ 2718 15-02-2007 09:57 | |
сообщение от модератораРуслану Богатырёву:
Возможно, вы пропустили этот момент, но pepper получил в этом форуме пожизненный запрет что-либо писать, поэтому отвечать ему не стоит - все его посты всё равно будут удаляться, и ваши ответы повиснут в воздухе.
№ 2717 15-02-2007 08:55 | |
Ответ на »сообщение 2715« (AVC)
___________________________
Ответ на »сообщение 2714« (pepper)
___________________________
В Обероне ближайший аналог конструктора -- фабричная функция.
В КП можно гарантировать (с помощью компилятора), что объект будет создан только посредством фабричной функции.
Это можно сделать как минимум двумя путями: с помощью LIMITED (конкретный тип экспортируется, но создать его самому нельзя) и с помощью ABSTRACT (конкретный тип не экспортируется, прячась за абстрактным интерфейсом).
Опять наверно речь идет не о Обероне, а о КП... Ну да ладно.
В Обероне же можно экпортировать только тип записи (без внутреннего содержимого) + указатели на функции (методы класса). Модуль экспортирующий данную запись должен содержать и экпортировать:
Имя записи + поля её процедурного типа (ака методы)
"Конструктор" - инициализатор экземпляра этой функции.
Должен содержать, но НЕ ДОЛЖЕН экпортировать функции для работы с этой записью.
Т.о. конструктор-инициализатор создает новый экземпляр (либо получает уже созданый полуфабрикат), переводит состояние записи в предопределенный вид (инициализирует), выставляет и сопостовляет процедурные переменные записи функциям для работы с этим типом записей содержащиеся в данном модуле. После чего с данным экземпляром записи (ака объектом, или переменной или еще как) можно уже работать, вызывая её соотв. "методы" - процедурные переменные.
Т.е. создать то экземпляр записи вне модуля будет конечно можно, но толку от этого если с ней все равно работать нельзя? Ведь мы не знаем внутреннюю её структуру...
Единственная дыра в такой модели - можно навести кашу в процедурных переменных записи (они то открыты) - например поменять местами (открыты то не только на чтение, но и на запись!) и передать эту запись уже куда-то во вне с "испорчеными" методами. Но в Обероне-2 можно эти переменные процедурные экспортировать как "-" т.е. в режиме RO. В этом случае возможности третьих лиц как-то попортить экземпляр записи я уже не вижу.
Добавить свое сообщение
Отслеживать это обсуждение
Дополнительная навигация: |
|