Форум: "Потрепаться";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
ВнизНеобходимость "is"... Найти похожие ветки
← →
Cosinus © (2004-07-05 15:03) [0]Вот у меня такой вопрос. Допустим у меня есть функция, которой в качестве параметра передается в том числе и Sender, например
Function WaitChar(sender:TObject;Timeout:integer):boolean;
Я всегда делал так
if (sender is TComponent) then
with (sender as TComponent) do begin
......
......
end;
Но недавно возник вопрос, а нужен ли этотis
? Я же сам заранее знаю, что мне надо туда слать только, ну например TEdit, и ничего больше. Так зачем я делаю лишнюю проверку? Что вы мне скажите по этому поводу?
← →
Sandman25 © (2004-07-05 15:06) [1]1. as не нужен, если уже была проверка.
2. ИМХО лучше так:
Assert(Sender is TComponent);
with TComponent(Sender) do
На этапе проектирования работают assert, поэтому если я ошибся и вызвал с неверным параметром, то будет выведено сообщение об ошибке. Когда программа уже готова, assert отключаются (Project-Options-Compiler) и тем самым убираются все "избыточные" проверки.
← →
Паниковский © (2004-07-05 15:07) [2]Cosinus
нужен
можно передать все что угодно
например
TMySuperGiperClass = class(TObject)
end;
var
MySuperVar:TMySuperGiperClass;
implementation
...
WaitChar(MySuperVar,10); <--- вот тут ахтунг!!!!!
...
end;
← →
Cosinus © (2004-07-05 15:16) [3]>>Sandman25 © (05.07.04 15:06) [1]
Спасибо, буду смотреть про Assert
>>Паниковский © (05.07.04 15:07) [2]
Да я понимаю, что передать можно все что угодно, но в данном вопросе я имел ввиду случаи, когда параметр, если можно так сказать "жестко зашит" в теле. Т.е. он не создается динамически и не берется откуда-нибудь, а просто есть в тексте несколько, допустим 10 строк вида WaitChar(MyComponent,10), где MyComponent - это константа, допустим Edit1. По идее проверять не надо, это все равно, что еще делать проверку является ли WaitTime числом... Но может есть какие-нибудь подземные камни и т.д.? Я собстнА это хотел узнать.
← →
DiamondShark © (2004-07-05 15:22) [4]
> Sandman25 © (05.07.04 15:06) [1]
> Когда программа уже готова, assert отключаются
Хе хе ;)
И остаётся молиться, что тестирование покрыло все возможные комбинации.
← →
MBo © (2004-07-05 15:26) [5]if (sender is TComponent) then
//as во второй строке уже не нужно
with TComponent(sender) do begin
← →
Sandman25 © (2004-07-05 15:27) [6][4] DiamondShark © (05.07.04 15:22)
Ну, если человек не уверен, что стОит отключать assert, то он их может и не отключать. В качестве бонуса получим номер строки при ошибке. А если воспользуемся и вторым параметром assert, то можно добиться еще более полезной функциональности.
← →
Cosinus © (2004-07-05 15:37) [7]>>MBo © (05.07.04 15:26) [5]
А не подскажите, какая принципиальная разница между
with (sender as TComponent) do begin
и?
with TComponent(sender) do begin
← →
Sandman25 © (2004-07-05 15:39) [8][7] Cosinus © (05.07.04 15:37)
as вызывает TObject.InheritsFrom
прямое преобразование ничего не делает - имеем выигрыш в скорости
← →
MBo © (2004-07-05 15:42) [9]>какая принципиальная разница между
при as делается проверка, но она после is излишня
← →
Cosinus © (2004-07-05 15:53) [10]Спасибо за разъяснения
← →
DiamondShark © (2004-07-05 15:54) [11]
> Cosinus © (05.07.04 15:37) [7]
as делает проверку на совместимость типа. Если типы не совместимые, генерируется исключение.
← →
Mim1 © (2004-07-05 18:14) [12]А я бы сделал так
with sender as TComponent do begin
Если уж пришло чтото не хорошее то exception а для if нужно писать вторую ветвь если условие не сработало.
← →
Esu © (2004-07-05 18:26) [13]помоему идеально с assert, если уж не тот объект передали то один фиг что-то нехорошее случится, так хоть понятно где :)
← →
iZEN © (2004-07-05 18:28) [14]Операторы is в Delphi и intanceof в Java сильно портят идеологию ООП. Я не использую их лет пять уже (в Delphi приходилось иногда).
А всё потому, что (не)знание типа ничего не даёт, если в метод передана ссылка на ("не тот")объект - всё дело в дизайне.
В Java instanceof даже лишний, не нужен нигде (странно, но в библиотеках он встречается на каждом шагу, хотя видно, что можно было бы обойтись и без него).
P.S. Этот вопрос обсуждается в книжках и у Фаулера, и у Буча, и у "банды четырёх". Все сходятся в одном: можно обойтись без этого.
← →
DiamondShark © (2004-07-05 18:31) [15]
> Esu © (05.07.04 18:26) [13]
> помоему идеально с assert, если уж не тот объект передали
> то один фиг что-то нехорошее случится, так хоть понятно
> где :)
С as тоже понятно где.
← →
Игорь Шевченко © (2004-07-05 18:32) [16]
> Операторы is в Delphi и intanceof в Java сильно портят идеологию
> ООП
> P.S. Этот вопрос обсуждается в книжках и у Фаулера, и у
> Буча, и у "банды четырёх". Все сходятся в одном: можно обойтись
> без этого.
А поточнее, где это в книжках обсуждается ? А то я матчасть забыл..
← →
Esu © (2004-07-05 18:34) [17]DiamondShark © (05.07.04 18:31) [15]
as одним махом из кода не уберешь.... Собственно от ситуации зависит.
← →
DiamondShark © (2004-07-05 18:34) [18]
> Операторы is в Delphi и intanceof в Java сильно портят идеологию ООП.
С этого места подробнее.
> Все сходятся в одном: можно обойтись без этого.
(шёпотом) Без ООП тоже можно обойтись.
← →
DiamondShark © (2004-07-05 18:38) [19]
> Esu © (05.07.04 18:34) [17]
> DiamondShark © (05.07.04 18:31) [15]
> as одним махом из кода не уберешь.... Собственно от ситуации
> зависит.
А зачем их оттуда убирать?
Про убирание асертов из релиза я говорил уже: после отключения асертов остаётся молиться, что тесты покрыли все возможные значения. Особенно если дальше используется небезопасное приведение типов.
← →
Esu © (2004-07-05 18:46) [20]
> DiamondShark © (05.07.04 18:38) [19]
Говорю ведь что от ситуации зависит :) Ну если очень хочется быстрого кода... Если это не важно то ставлю as.
← →
DiamondShark © (2004-07-05 18:56) [21]
> Esu © (05.07.04 18:46) [20]
> Говорю ведь что от ситуации зависит :)
Я сильно подозреваю, что ситуация -- неправильный дизайн.
> Ну если очень хочется
> быстрого кода... Если это не важно то ставлю as.
Да ну?!
Давайте так: вы мне пример кода, где as, по-вашему, мешает быстроте, а я вам описание допущенных ошибок дизайна.
← →
iZEN © (2004-07-05 20:22) [22]/**DiamondShark © (05.07.04 18:34) [18]
> Операторы is в Delphi и intanceof в Java сильно портят идеологию ООП.
С этого места подробнее.
*/
Замена условного оператора полиморфизмом (Replace Conditional with Polymorphism).
Есть условный оператор, поведение которого зависит от типа объекта.
<...>
Одним из наиболее внушительно звучащих слов из жаргона объектно-ориентированного программирования является полиморфизм. Сущность полиморфизма состоит в том, что он позволяет избежать написания явных условных операторов, когда есть объекты, поведение которых различно в зависимости от их типа. В результате оказывается, что операторы switch, выполняющие переключение в зависимости от кода типа, или операторы if-then-else, выполняющие переключение в зависимости от строки типа, в объектно-ориентированных программах встречаются значительно реже.
<...>
Наибольшая отдача имеет место тогда, когда один и тот же набор условий появляется во многих местах программы. Если необходимо ввести новый тип, то приходится отыскивать и изменять все условные операторы [работающие на основе определения типа instanceof]. Но при использовании подклассов достаточно создать новый подкласс и обеспечить в нём соответствующие методы. Клиентам класса не надо знать о подклассах [новых типах], благодаря чему сокращается число зависимостей в системе и упрощается её модификация.
Мартин Фаулер "Рефакторинг. Улучшение существующего кода". Там же раскрывает сущность объекта "Null".
Идея о неудобности instanceof ярко описана у Эрика Аллена в кн. "Типичные ошибки проектирования" в главе "Двойной спуск", и это фактически проходит через всю книгу. Диспетчерирование вызовов, зависящее от типа объекта, решается гораздо изящнее применением полиморфизма.
У Гради Буча в кн. "ООА и П", в гл. "Классы и объекты" случай использования диспетчирования вызовов в зависимости от типа объекта носит название мономорфизма: в случае Pascal-я и ADA требуется описать длинный блок case или if-then на этапе написания программы с жёсткой зашивкой всех типов, а, например, в C++ на этой стадии уже можно использовать полиморфизм, выбирая позднее связывание и сокращая количество строк до одной DisplayItem->draw().
/*
(шёпотом) Без ООП тоже можно обойтись.
*/
Кто же Вам запрещает? Обходитесь. ;)
← →
DiamondShark © (2004-07-05 21:18) [23]
> iZEN © (05.07.04 20:22) [22]
> Одним из наиболее внушительно звучащих слов из жаргона объектно-ориентированного
> программирования является полиморфизм.
Каким образом использование is/as мешает использовать полиморфизм?
> Диспетчерирование вызовов, зависящее от типа объекта, решается
> гораздо изящнее применением полиморфизма.
С вас изященое решение с применением полиморфизма вот такого вот фрагмента:
try
...
except
on E: EMathError do ...
on E: EInOutError do ...
...
end;
> У Гради Буча в кн. "ООА и П", в гл. "Классы и объекты" случай
> использования диспетчирования вызовов в зависимости от типа
> объекта носит название мономорфизма
Гради Буч является религиозным фанатиком фундаменталистской секты Ц-с-крестами.
Даю намёк: постарайтесь найти разницу между ООП по Бучу и компонентным программированием.
Кстати, что такое "позднее связывание" в Ц++?
> /*
> (шёпотом) Без ООП тоже можно обойтись.
> */
> Кто же Вам запрещает? Обходитесь. ;)
А вы, оказывается, гораздо более деревянный, чем я предполагал.
← →
iZEN © (2004-07-05 21:38) [24]/**DiamondShark © (05.07.04 21:18) [23]
> iZEN © (05.07.04 20:22) [22]
> Одним из наиболее внушительно звучащих слов из жаргона объектно-ориентированного
> программирования является полиморфизм.
Каким образом использование is/as мешает использовать полиморфизм?
*/
Я говорил про is/instanceof. Использование информации о типах - RTTI практически в явном виде - ведёт к моноформизму и отказу от полиморфизма (позднего связывания).
/*
> Диспетчерирование вызовов, зависящее от типа объекта, решается
> гораздо изящнее применением полиморфизма.
С вас изященое решение с применением полиморфизма вот такого вот фрагмента:
try
...
except
on E: EMathError do ...
on E: EInOutError do ...
...
end;
*/
Код с "душком": несколько исключительных ситуаций совершенно разной группы. РЕФАКТОРИТЬ!
1) Разделять метод на два и больше (по количеству разногруппных "ошибок").
2) Строить иерархию обработчиков ошибок, переопределяя метод abstract void handle(Error e).
3) Не обрабатывать "ненужные" на этом уровне исключения, а переправлять их raise e вызывающему коду наверх и там обрабатывать.
← →
iZEN © (2004-07-05 21:46) [25]/**> У Гради Буча в кн. "ООА и П", в гл. "Классы и объекты" случай
> использования диспетчирования вызовов в зависимости от типа
> объекта носит название мономорфизма
Гради Буч является религиозным фанатиком фундаменталистской секты Ц-с-крестами.
*/
Когда он писал про ООП, ObjectPascal не был широко распространён (были разные версии), SmallTalk слишком сложен, C++ был "на коне", поэтому он выбрал этот язык для иллюстрации ООП.
Впоследствии начал комбинировать иллюстрации на C++ и Java, потом окончательно перешёл на Java для иллюстрации принципов UML в реальном языке.
/*
Кстати, что такое "позднее связывание" в Ц++?
*/
Просто парадигма, по-настоящему реализованная только в некоторых версиях C++.
/*
Даю намёк: постарайтесь найти разницу между ООП по Бучу и компонентным программированием.
*/
Зачем искать разницу, если одно вытекает из другого?
← →
iZEN © (2004-07-05 21:50) [26]Заключение: не надо выпячивать явные механизмы RTTI в прикладной области, но нужно пользоваться скрытыми возможностями.
← →
DiamondShark © (2004-07-05 22:56) [27]
> Я говорил про is/instanceof. Использование информации о
> типах - RTTI практически в явном виде - ведёт к моноформизму
> и отказу от полиморфизма (позднего связывания).
Заклинания можно повторять долго.
Каким именно образом ведёт? Что, из языка исключён механизм наследования?
> Код с "душком": несколько исключительных ситуаций совершенно
> разной группы. РЕФАКТОРИТЬ!
> 1) Разделять метод на два и больше (по количеству разногруппных
> "ошибок").
> 2) Строить иерархию обработчиков ошибок, переопределяя метод
> abstract void handle(Error e).
> 3) Не обрабатывать "ненужные" на этом уровне исключения,
> а переправлять их raise e вызывающему коду наверх и там
> обрабатывать.
1) Разделить, конечно, можно. Только это не имеет отношения к полиморфизму
2) И что с этой иерархией делать? Как обработать конкретный тип сообщения?
3) Это main loop приложения.
Другой пример, из Оберон системы.
MODULE StdMessages;
TYPE
AbstractMessage* = POINTER TO ABSTRACT RECORD END;
KeyboardMessage* = POINTER TO RECORD(AbstractMessage)
KeyCode*: INTEGER;
END;
MouseMessage* = POINTER TO RECORD(AbstractMessage)
X*, Y*: INTEGER;
Buttons*: SET;
END;
(* ещё какие-то типы месажей *)
...
END StdMessages.
В других модулях могут быть объявлены другие расширения AbstractMessage
MODULE MyApp
...
TYPE
Application = RECORD(GenericApplication)
...
END;
...
PROCEDURE (IN a: Application)HandleMessage(m: AbstractMessage);
BEGIN
WITH
m: KeyboardMessage DO ... |
m: MouseMessage DO ... |
ELSE a.HandleMessage^(m)
END;
END HandleMessage;
Несколько слов, почему сделано именно так.
Оберон -- типобезопасный (не путать с типа безопасным ;)) язык с автоматическим управлением памятью. В языке нет приведения типов, поэтому записи, подобные виндовому MSG невозможны. Отсутствуют и записи с вариантами, т.к. это, во-первых, дыра в безопасности типов, и, во-вторых, помеха автоматическому менеджеру памяти. Зато введено расширение типов (наследование).
Как видно, оператор WITH преобразован для работы именно как выбор по ран-тайм типу.
← →
iZEN © (2004-07-05 23:08) [28]А если появится JoystickMessage надо программу переписывать и искать ВСЕ места, где проверяется сообщения от внешних устройств(?).
← →
DiamondShark © (2004-07-05 23:11) [29]
> iZEN © (05.07.04 21:50) [26]
> Заключение: не надо выпячивать явные механизмы RTTI в прикладной
> области, но нужно пользоваться скрытыми возможностями.
Общие слова в стиле заклинания.
На основе какого-то фрагмента кода из VCL можно привести пример исполнения "по-правильному"?
Кстати, о скрытых возможностях.
Не находите, что логичнее была бы ситуация, если бы в языке не нужно было бы искать "скрытых возможностей", а наоборот, наиболее правильные возможности явно бы следовали из спецификации языка?
В данном случае имеем два полюса: Ц с крестами, где толпа религиозных фанатиков иступлённо выискивает уже полвека "скрытые возможности" в нечто, что больше напоминает помехи в линии связи, чем язык и о которых сам автор не подозревал, и виртовские языки, где сначала формулируются необходимые возможности, а потом пишется спецификация языка, из которой эти возможности самым очевидным образом следуют.
Ну а борландовский продукт где-то посередине. Причём из-за явной генетической связи его оказалось трудно сильно испортить ;)
← →
iZEN © (2004-07-05 23:14) [30]ELSE a.HandleMessage^(m) пропустил - фразу про JoystickMessage беру обратно.
← →
DiamondShark © (2004-07-05 23:14) [31]
> iZEN © (05.07.04 23:08) [28]
Если программа писалась раньше, чем появился джойстик, то она и не должна реагировать на джойстик. Не правда ли?
← →
iZEN © (2004-07-05 23:16) [32]/**DiamondShark © (05.07.04 23:11) [29]
Не находите, что логичнее была бы ситуация, если бы в языке не нужно было бы искать "скрытых возможностей", а наоборот, наиболее правильные возможности явно бы следовали из спецификации языка?
*/
Я не то имел ввиду.
Парадигма полиморфизма настолько кажется простой, что почему-то её не так часто используют (из-за лении чаще всего - не хочется писать параллельную иерархию). Вспомните паттерн Visitor.
← →
Игорь Шевченко © (2004-07-05 23:19) [33]
> Идея о неудобности instanceof ярко описана у Эрика Аллена
> в кн. "Типичные ошибки проектирования" в главе "Двойной
> спуск",
А книжка, кстати, макулатура, по моему мнению.
← →
iZEN © (2004-07-05 23:20) [34]/**DiamondShark © (05.07.04 23:14) [31]
> iZEN © (05.07.04 23:08) [28]
Если программа писалась раньше, чем появился джойстик, то она и не должна реагировать на джойстик. Не правда ли?
*/
Нет не так. Она должна безболезненно расширятся.
Что если будут повсеместно использовать световое перо вместо мыши?
Тогда лёгким движением руки пишем "драйвер" и подсовываем его программе, а старый "драйвер" выбрасываем (или оставляем): сама программа остаётся неизменной, но расширяемой за счёт компонентного подхода.
← →
iZEN © (2004-07-05 23:22) [35]Классический плагин-фреймворк.
← →
Игорь Шевченко © (2004-07-05 23:22) [36]DiamondShark © (05.07.04 23:11)
> В данном случае имеем два полюса: Ц с крестами, где толпа
> религиозных фанатиков иступлённо выискивает уже полвека
> "скрытые возможности" в нечто, что больше напоминает помехи
> в линии связи, чем язык и о которых сам автор не подозревал
Чем ж вам так язык С++ насолил ? :)
← →
iZEN © (2004-07-05 23:23) [37]/**Игорь Шевченко © (05.07.04 23:19) [33]
> Идея о неудобности instanceof ярко описана у Эрика Аллена
> в кн. "Типичные ошибки проектирования" в главе "Двойной
> спуск",
А книжка, кстати, макулатура, по моему мнению.
*/
А по-моему, очень стоящая книжка.
← →
iZEN © (2004-07-05 23:28) [38]/**DiamondShark © (05.07.04 23:11) [29]
> iZEN © (05.07.04 21:50) [26]
> Заключение: не надо выпячивать явные механизмы RTTI в прикладной
> области, но нужно пользоваться скрытыми возможностями.
Общие слова в стиле заклинания.
На основе какого-то фрагмента кода из VCL можно привести пример исполнения "по-правильному"?
*/
VCL вообще-то неправильно спроектирована с точки зрения ООД.
← →
Игорь Шевченко © (2004-07-05 23:30) [39]iZEN © (05.07.04 23:23)
> А по-моему, очень стоящая книжка.
Может быть мне просто не нравится изложение экстремальщиков, их священный трепет с которым они произносят банальные истины. Что Бек, что Аллен - всех их объединяет, IMHO, какой-то догматический подход - делай так и будет тебе рулез немеряный, а не будешь делать - будет тебе сакс и мастдай пожизненный. И фразы вроде "Красный-Зеленый-Рефакторинг - вот мантра программиста" у меня почему-то отбивают охоту к прочтению (это из Бека: "Разработка через тестирование")
← →
iZEN © (2004-07-05 23:39) [40]to Игорь Шевченко © (05.07.04 23:30) [39]
Вы имеете что-то против рефакторинга как понятия процесса улучшения чего-то?
Лично я не связываю рефакторинг с экстремальным программированием.
Рефакторинг - это "утряска", приведение в божеский вид уже работающего кода. Если код изначально нерабочий, то его невозможно рефакторить - его нужно написать сначала ;).
Страницы: 1 2 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.04 c