Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.07.25;
Скачать: CL | DM;

Вниз

Необходимость "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;
Скачать: CL | DM;

Наверх




Память: 0.6 MB
Время: 0.048 c
14-1088689475
KilkennyCat
2004-07-01 17:44
2004.07.25
11500 дней!


4-1086769691
Elf
2004-06-09 12:28
2004.07.25
Структруры и Винды


14-1088890025
XenoM
2004-07-04 01:27
2004.07.25
Skins


1-1089409823
nick_mas
2004-07-10 01:50
2004.07.25
Как отключить процедуру RadioButton1.Click для "Down" и "Up"???


4-1086467408
AndreySoft
2004-06-06 00:30
2004.07.25
Как запретить нажатие клавиши "WINDOWS"