Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 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.657 c
1-1089698381
DelphiNew
2004-07-13 09:59
2004.07.25
Ещё раз про TreeView


3-1088577412
zorik
2004-06-30 10:36
2004.07.25
Нужно написать запрос


4-1087209443
stas
2004-06-14 14:37
2004.07.25
Распределение прав доступа в NT


3-1088494421
souLLamer
2004-06-29 11:33
2004.07.25
SQL - игнорирование регистра букв.


4-1087278653
Tolea
2004-06-15 09:50
2004.07.25
Перенаправить стандартны ввод с клавиатуры





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский