Переключение на Главную Страницу Страницы: 1 2 3 [4] 5  ОтправитьПечать
Очень популярная тема (более 25 ответов) ПолучитьТекущийОбъект() (число прочтений - 38816 )
fez
Forum Administrator
1c++ power user
Отсутствует


I wanted to cry, but the
tears wouldn't come

Сообщений: 2712
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ПолучитьТекущийОбъект()
Ответ #45 - 02. Июня 2006 :: 12:45
Печать  
kms писал(а) 02. Июня 2006 :: 12:21:
Ну нельзя этого делать, пойми, пожалуйста. Нельзя.

Угу, и любовь тоже нельзя купить. И суслика я не вижу.

Цитата:
Механизм контроля предлагаю включать по запросу.

Как быдет выглядеть этот запрос?
  
Наверх
www  
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #46 - 02. Июня 2006 :: 12:48
Печать  
fez
Не унывай! Все будет хорошо.

orefkov писал(а) 01. Июня 2006 :: 11:44:
kms писал(а) 01. Июня 2006 :: 11:38:
Проблемы 2:
1. Проблема реализации, которая по умолчанию позволяет это делать.
2. Проблема квалификации кадров, котроые пользуются такой реализацией и пребывают в счастливом неведении.

Исправляя первую проблему, ты наткнешся на жестокое сопротивления второй Улыбка

У меня много было мыслей по грамотной реализации ООП с учетом накопленного в 1С++ опыта.
Однако все они упирались в "обратную совместимость".

Я думаю, Саня не про тебя писал, нет?

Цитата:
Как быдет выглядеть этот запрос?

Ну сделаем кнопку, как сейчас "оптимизация" или "проверка типов".
И метод добавим, типа "Сервис.ВключитьКонтрольИерархии()". ОК?
  

De quelle planète es-tu?
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #47 - 02. Июня 2006 :: 12:49
Печать  
Че вы паритесь?
В-принципе, это уже есть в исходниках, только наружу не торчит.
Смотрим
CSetOfHierarchy::GetComponentClassCurExModule
К этому методу как-раз и обращается ПолучитьБазовыйКласс, для исключения полиморфности при поиске.
  
Наверх
 
IP записан
 
sedmin
1c++ developer
Отсутствует


I Hate Fat YaBB 2!

Сообщений: 862
Зарегистрирован: 24. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #48 - 02. Июня 2006 :: 12:51
Печать  
Тесты для наследования кое-какие имеются. Для Орефкова тоже парутестов можно написать. Если у кого что отвалится - добавим тестов.
Так что дерзай!
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #49 - 02. Июня 2006 :: 12:51
Печать  
orefkov писал(а) 02. Июня 2006 :: 12:49:
Че вы паритесь?

У нас традиция - каждый год 31 числа мы с друзьями... Улыбка

Ну по реализации - это мы все равно тебя будем спрашивать.
А по концепции - ты что думаешь?
  

De quelle planète es-tu?
Наверх
 
IP записан
 
fez
Forum Administrator
1c++ power user
Отсутствует


I wanted to cry, but the
tears wouldn't come

Сообщений: 2712
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ПолучитьТекущийОбъект()
Ответ #50 - 02. Июня 2006 :: 12:54
Печать  
kms писал(а) 02. Июня 2006 :: 12:48:
Цитата:
Как быдет выглядеть этот запрос?

Ну сделаем кнопку, как сейчас "оптимизация" или "проверка типов".
И метод добавим, типа "Сервис.ВключитьКонтрольИерархии()". ОК?

Неа. Ибо это потребует одновременной переработки ВСЕЙ конфигурации. Переходный период будет невозможен.
Поэтому я и предлагаю сделать через доп. метод. Чтобы можно было одни и те же методы в одном и том же классе вызывать по-разному.
  
Наверх
www  
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #51 - 02. Июня 2006 :: 12:57
Печать  
Ну, давай я подумаю. Может быть, это удастся включать в пределах класса?
Но это ведь детали уже, придумаем что-нибудь.

P.S.
Может, я это декларатором сделаю. Все равно надо отключение кеширования добавлять.
Значит, все равно разбираться придется.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #52 - 02. Июня 2006 :: 15:12
Печать  
Цитата:
А по концепции - ты что думаешь?

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

Может, просто пропустил.

Итак, давайте начнем от печки.

В-первую очередь хочу заметить, что 1С++ появился не как очередной вариант академического языка для исследования глубинных проблем ООП и постановки экспериментов, а механизм для решения ПРАКТИЧЕСКИХ задач, стоящих перед разработчиком програм на платформе V77, труднорешаемых или плохосопровождаемых стандартными средствами платформы. Но базирующийся на самой платформе, с присущими ей недостками, которые надо принять как данность. И потому менять коренным образом ранее существующее поведение суть проявление неуважения к пользователям 1С++, написавшим на ее основе горы кода.

Во-вторых, идеи с флагами/опциями меня всегда честно говоря коробят. Потому что современем они выливаются в "здесь играем, здесь не играем, а здесь рыбу заворачивали", что вносит совершенную сумятицу в головы как пользователей, так и разработчиков, пытающихся развивать систему далее.

Итак, перед нами стоит дилемма. С одной стороны, хочется оставить поведение написаного кода таким же, как ранее, с другой - иметь возможность там где это нужно, использовать поведение, трактуемое как правильное в свете последних решений ЦК КП принципов ООП.

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

Рассмотрим имеющуюся проблему подробнее:
Итак, обсуждаем мы как я понял
Код
Выбрать все
Сам(Контекст).ВызовМетода();
 


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

Что хотим:
При вызове методов гарантированно обращаться только к методам либо своих предков, либо своих прямых потомков.
Плюсы:
- организация вызова из метода базового объекта методов его объектов-наследников (виртуальность).
- Большая безопасность в использовании классов и изолированность реализаций друг от друга.
Минусы:
- не сделать подмешивания.
- многий ранее написанный код по такой схеме не заработает.

Плохо ли текущее поведение, хорошо ли, правильно, неправильно, менять его мы не можем. Не имеем права даже, если мы уважаем пользователей компоненты. Ведь наверняка существуют ПРАКТИЧЕСКИЕ РАБОТАЮЩИЕ решения, основанные на этом поведении.

Рассмотрим вариант с
Код
Выбрать все
Сам(Контекст).ТекущийКласс()
 


То есть метод получить в методе объекта "настоящую" ссылку на самого себя, вместо ссылки на конечный класс.
Справедливости ради отмечу, что в первых версиях 1С++ (oxy.dll), Сам(Контекст) так и работал.
Плюсы:
- При вызове методов мы гарантированно обращаемся к методам планируемых объектов.
Минусы:
- Нет возможности виртуального вызова.
Этот минус сводит всё на нет.

ЭТО ВСЕ ПРЕАМБУЛА и словесный понос.
Теперь по делу.
КОНКРЕТНЫЕ АНИТИКРИЗИСНЫЕ ПРЕДЛОЖЕНИЯ.

Упираемся мы в реализацию алгоритма поиска метода по имени. Иногда нам нужен поиск, как сейчас есть, а иногда - "правильный" поиск.
Алгоритм поиска задается объектом, от которого начинается поиск, и учитывая, что никаких флагов городить мы не хотим, один объект имеет один алгоритм поиска. Следовательно, либо нам надо для поиска использовать другой объект, либо как-то менять семантику вызова метода, что-бы задействовать другой алгоритм для того-же объекта.
Решение по первому пути: объект-прокси.
что-то типа
Код
Выбрать все
Сам(Контекст).ПолучитьПравильныйОбъект().ВызовМетода();
 


ПолучитьПравильныйОбъект() - возвращает объект-прокси, знающий о конечном классе, текущем контексте вызова, и осуществляющий "правильный" поиск метода и перенаправление обращений к методам.

Решение по второму пути:
Код
Выбрать все
ВызовМетода();
// либо
ИмяКласса__класс__ВызовМетода();
 


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

Думаем, господа.
  
Наверх
 
IP записан
 
fez
Forum Administrator
1c++ power user
Отсутствует


I wanted to cry, but the
tears wouldn't come

Сообщений: 2712
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ПолучитьТекущийОбъект()
Ответ #53 - 02. Июня 2006 :: 15:27
Печать  
Я все это время говорил о первом варианте с объектом-прокси.
Насколько я понимаю - на данном этапе это самый легкореализуемый вариант. Вдобавок он мне кажется синтаксически наиболее прозрачным.

По поводу "дикого увеличения перформанса" для второго варианта. Лично мое мнение непоколебимо: по сравнению с обращением к данным - это слезы и крохи.
  
Наверх
www  
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #54 - 02. Июня 2006 :: 16:16
Печать  
orefkov
По порядку.

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

По одной простой причине:
Цитата:
Во-вторых, идеи с флагами/опциями меня всегда честно говоря коробят. Потому что современем они выливаются в "здесь играем, здесь не играем, а здесь рыбу заворачивали", что вносит совершенную сумятицу в головы как пользователей, так и разработчиков, пытающихся развивать систему далее.

Объясни мне, чем ввод нового объекта - прокси, лучше флагов?
Это абсолютно то же самое. Разве нет?

Приведет к тому же, чего ты опасаешься: разномастный код, разные принципы ООП, разные подходы к разработке, разные проблемы.
Нет, я этого не хочу.
Мы должны 1 раз сделать правильно, объяснить свою позицию людям, и обеспечить нормальный переходный период, когда работают обе технологии. Для этого и нужен глобальный флаг.

По поводу прокси/не прокси.
Я думаю, что мы в состоянии оптимизировать процедуры поиска.
Кроме того, ты правильно сказал, нужно контролировать доступ к свойствам и методам в пределах интерфейса.
Кроме того, есть еще "проблемные" методы типа НазначитьБазовыйКласс(), по которым я еще как-нибудь выскажусь.

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

De quelle planète es-tu?
Наверх
 
IP записан
 
sedmin
1c++ developer
Отсутствует


I Hate Fat YaBB 2!

Сообщений: 862
Зарегистрирован: 24. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #55 - 02. Июня 2006 :: 21:54
Печать  
Мне хотелось бы выяснить еще несколько вопросов. Надеюсь, они будут полезны и для вас.

Речь пойдет о текщем положении дел, не о планах.
Результатом выполнения выражения
Код
Выбрать все
ТипЗначенияСтр(Сам().ПолучитьБазовыйКласс("БазовыйКласс"))  


будет "БазовыйКласс".

А на самом ли деле результатом вызова ПолучитьБазовыйКласс() будет объект типа "БазовыйКласс"? Или это будет прокси-объект?

Ведь если это будет на самом деле БазовыйКласс, то тогда вызовы Сам.ПолучитьБазовыйКласс("БазовыйКласс").МетодБазы() и Сам.БазовыйКласс::МетодБазы() приведут к разным результатам. Ведь если МетодБазы() производит вызов виртуального метода, то произойдет вызов родительского виртуального метода, а не дочернего.

Но, мне помнится, я уже пользовался таким вызовом и вызовы виртуальных методов проходили верно  (ручаться не буду). Поэтому есть подозрение, что Сам().ПолучитьБазовыйКласс() возвращает некий прокси-объект, который во время вызова его методов преобразуется в в объект реального класса.

Если же возращается объект родительского класса, то что следует написать, чтобы получился вызов  Сам.БазовыйКласс::МетодБазы()?
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #56 - 03. Июня 2006 :: 04:14
Печать  
kms писал(а) 02. Июня 2006 :: 16:16:
Я выступаю и выступал изначально за вариант, который ты предлагаешь делать через прокси.
Только я хочу, чтобы этот объект возвращался непосредственно через Сам(Контекст).

Да как ты это сделаешь, если при этом старый клиентский код перестанет работать так, как работал? Ты согласен с предложенным мною принципом - где ты хочешь использовать новый функционал, ты должен писать по-новому?

kms писал(а) 02. Июня 2006 :: 16:16:
Объясни мне, чем ввод нового объекта - прокси, лучше флагов?

Тем, что во-первых точность определения используемого алгоритма поиска увеличивается до конкретного места вызова. Любой вариант с флагами будет ограничен с разным уровнем - до всей  конфигурации, либо до отдельного класса, не более.
Во-вторых, у нас будет просто CComponentClass::FindMethod и CProxyClass::FindMethod, две совершенно независящие ни друг от друга, ни от флагов реализации.
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #57 - 03. Июня 2006 :: 04:36
Печать  
sedmin писал(а) 02. Июня 2006 :: 21:54:
Мне хотелось бы выяснить еще несколько вопросов. Надеюсь, они будут полезны и для вас.


Попытаюсь внести ясность.
То, что мы сейчас называем наследованием в 1С++, на внутреннем уровне реализовано агрегацией нескольких объектов (базовые классы, конечный класс) с автоделегированием их методов.

Поиск метода осуществляется всегда от контекста (подобъекта класса), к которому применен вызов метода, снизу-вверх слева-направо вверх по иерархии строения класса. Вниз по иерархии поиск никогда не идет. Обращение же из базового класса к методам наследникам происходит за счет того, что модулю каждого подобъекта класса назначается контекст - ссылка на конечный объект.
Поэтому Сам(Контекст) - в любом из модулей подобъектов всегда указывает на конечный класс.

Делая же База=Сам(Контекст).ПолучитьБазовыйКласс(), мы получаем из конечного объекта ссылку на подобъект базового класса. Если теперь вызвать метод переменной База, поиск метода осуществляется не от конечного объекта, а от подобъекта базового класса, те только среди его методов и методов его предков. То есть таким образом мы гарантированно обращаемся к методу базового класса. Если же в этом методе базовый класс делает Сам(Контекст), он опять получит ссылку на конечный класс, и поиск метода опять пойдет с самого низа иерархии класса.

То есть вот три ключа к пониманию текущего роутинга методов:
1. Поиск всегда идет от объекта, к которому применен вызов метода, снизу-вверх слева-направо по иерархии строения объекта.
2. Сам(Контекст) всегда возвращает самый нижний по иерархии подобъект класса, имя которого было в СоздатьОбъект.
3. ПолучитьБазовыйКласс всегда возращает ссылку на подобъект базового класса.
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #58 - 03. Июня 2006 :: 04:56
Печать  
Можно сделать еще такой промежуточный вариант между Сам(Контекст) и прямым обращением к методам классов. Технически реализуется достаточно просто. Когда я пробовал сделать реализацию прямого обращения к методам классов, то так как мне надоело каждый раз писать Сам(Контекст), в каждом модуле я сделал две предопределенные функции, к к оторым можно обращатся напрямую:
Код
Выбрать все
вирт()
я()
 


вирт() - возвращает контекст конечного класса (как Сам(Контекст))
я() - возвращает контекст самого класса (типа как предлагали Сам(Контекст).ТекущийОбъект())

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

Таким образом получается так:
Код
Выбрать все
вирт().ВызовМетода(); // Полностью как Сам(Контекст).ВызовМетода();
я().ВызовМетода(); // Гарантированный поиск только в базовых классах
иерархия().ВызовМетода(); // Правильный поиск по иерархии класса, начиная с конечного
 


Может, это даже лучше сделать предопределенными свойствами, только надо проверять, как там с подсчетом ссылок будет. Типа
Код
Выбрать все
вирт.ВызовМетода(); // Полностью как Сам(Контекст).ВызовМетода();
я.ВызовМетода(); // Гарантированный поиск только в базовых классах
иерархия.ВызовМетода(); // Правильный поиск по иерархии класса, начиная с конечного
 


  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: ПолучитьТекущийОбъект()
Ответ #59 - 03. Июня 2006 :: 07:43
Печать  
orefkov
Я с тобой согласен.

Цитата:
Да как ты это сделаешь, если при этом старый клиентский код перестанет работать так, как работал? Ты согласен с предложенным мною принципом - где ты хочешь использовать новый функционал, ты должен писать по-новому?

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

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

Я просто боюсь, что участники этой ветки, конечно, все поймут правильно и смогут использовать новые и старые возможности правильно, так, как это нужно.

А вот со многими, скажем, начинающими разработчиками, будет путаница.
И для того, чтобы определить, где проблема, мы будем вынуждены вместо анализа флагов и деклараторов классов, анализировать весь код классов, потому что без этого будет совершенно неясно, в каких наборах используются CComponentClass и CProxyClass. Ты ведь знаешь, какой код можно написать при желании?

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

Я могу согласиться с тобой и Федором. Но мое мнение - надо оперировать более крупными блоками.
Это уменьшит наш головняк, да и людям, в конечном итоге, станет лучше.


В остальном тебя поддерживаю.

По поводу предопределенных процедур: Чтобы быть до конца последовательным:

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

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

вирт() пускай возвращает объект по старым или по новым правилам - в зависимости от настроек класса.

Тогда "иерархия" не нужна будет, и все будет прозрачно.
Принял правила - выполняй. Не принял - тоже хорошо, пользуйся нарушениями на здоровье.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1 2 3 [4] 5 
ОтправитьПечать