Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Адекватное количество обработчиков (http://www.flasher.ru/forum/showthread.php?t=152680)

arkadattx 21.03.2011 14:22

Адекватное количество обработчиков
 
Просьба к флеш-общественности разрешить спор.
Ситуация: есть некий интерфейс (кнопочки всякие, а не Interface), при клике (наведении и пр.) на каждую из них необходимо выполнять какие-то действия, часто схожие между собой.
Суть спора. Я склонен считать, что на каждую такую кнопку необходимо вешать свой слушатель с обработчиком (в результате будет создано несколько методов). Мой оппонент предлагает использовать один слушатель на контейнере, внутри которого определять тип объекта, по которому клацнули и затем switch-case-ом по имени определять необходимые действия (т.е. всего один метод).
Вот пример:
Код AS3:

private function onMouseEvent(e:MouseEvent):void
{
        if (e.target is ISkinButton)
        {
                switch (e.target.name)
                {
                        case "closeButton":
                        case "exitButton":
                        exit();
                        break;
                        case "plusButton":
                        text(1);
                        break;
                        case "minusButton":
                        test( -1);
                        break;
                }
        }
}

Кто прав и почему?

Александр Мостовой 21.03.2011 14:38

Мне удобно для каждой кнопочки создавать отдельный класс, который она наследуют от общего, оверрайдив обработчик для каждой, т.е. писать все это внутри класса кнопки. Удобно тем, что неважно знать где находится кнопка, можем кинуть ее в любой контейнер

wvxvw 21.03.2011 15:04

За свитч-кейс убивать сразу, это заразно. :) Ято Ява-оптимизаторы такое любят, т.как в ней написать обработчик события - это цельный класс с методами и имплементациями и т.п. Во флеше обработчик - это всего одна функция! А свитч искажает логику программы, усложняет тестирование и вообще чтение, при том, что если и есть какая-то разница в производительности - она на столько минимальна, что вы ее никогда не увидите. И шансы за то, что в том же свитче в итоге будут сделаны лишние телодвижения, которые эту самую производительность снова просадят.
Т.е. сравните:
Код AS3:

function close_clickHandler(event:Event):void {}
function open_clickHandler(event:Event):void {}
// и
function clickHandler(event:Event):void
{
        switch (event.target)
        {
                case foo:
                        break;
                case bar:
                        break;
                default: trace("???");
        }
}

Т.е. в первом случае логика работает железно: нажали на "close" -> попали в обработчик "close". В то время как во втором случае: нажали на "close" -> попали в неизвесный обработчик, где усилием воли мы разгадали, что же нужно делать. Но в последнем случае имеем еще одно логическое несоответсвие - у написаной нами фунции есть избыточный фунционал. А именно default кейс. А нужен он исходя из ТЗ? - нет. Помогает ли он функции работать лучше? - нет, даже наоборот, оставляет простор для ошибок и последующего неправильного ее использования. Кроме того, эта функция может "вдруг" быть переопределена в классе наследнике. И класс-наследник "вдруг" будет зависеть от ее результатов, но его абсолютно не интересует, что происходит с кнопкой open, а возможно и нет у него такой - а в этой функции она есть! И в тот момент, когда класс-наследник случайно удалит foo, то оба кейса будут указывать на один и тот же объект (null), что почти наверняка создаст аварийную ситуацию, которую, кроме всего прочего тяжело выявить.
Вот так вот. :)

Stargazer 21.03.2011 15:25

Голосую против case-ов.
Это искусственная конструкция, возникающая потому что кому-то лень написать 2 лишних строки (хотя отдельные функции и быстрее и проще написать и проще потом читать).

arkadattx 21.03.2011 15:54

wvxvw, спасибо за объяснения.
В данном проекте подобный функционал никогда не будет переопределяться. default отсутствует. То что "попали в неизвестный обработчик" (я так понимаю что речь идет скорее о неизвестной части обработчика) - можно заменить конструкцией типа
Код AS3:

if(name==ThisClass.CONSTANT_NAME){
//*****
return;
}

Таким образом мы уменьшаем количество возможных ошибок и гарантированном попадем в нужный участок обработчика.
При таком условии есть у такого подхода еще недостатки?
Александр Мостовой, Stargazer, спасибо за мнение, но хотелось бы больше конкретики и объективизма. Личные предпочтения каждого - дело такое... Не стабильны как мода.

wvxvw 21.03.2011 16:05

Для начала, default не может отсутствовать, то, что вы его не написали, еще на значит, что его нет. Он есть всегда, хотите вы того или нет. А за возвраты из функции в непредвиденных местах можно, если еще шевелится, контрольный выстрел сделать - хуже не будет. :)
Нет, еще раз, в switch'e вы делаете предположение, что event.current таргет а) существует, б) не равен нулю. При том, что оба эти предположения могут не выполнится. Т.е. вы предлагаете 100% работающий вариант заменить 99% работающим вариантом, аргументируя это чем? Улучшением производительности? На микрон? А если компилятор окажется в силах (в будущем) заинлайнить код обработчика? Так вы только просадите производительность вашим свитчем, т.как его будет труднее разделить на части и заинлайнить в разные места по частям. Но это уже гости из будущего :)
С другой стороны, написав свитч, вы усложните себе последующую разработку и сопровождение - опять же, такие жертвы только ради того, чтобы выиграть миллисекунду на вызове 1000 обработчиков?

kyzi007 21.03.2011 16:13

С автогенерацией кода конечно на каждую кнопку отдельный слушатель намного удобнее / красивее, только имена придумать:)

По мне все зависит от архитектуры.

Код AS3:

case "closeButton":
case "exitButton":
exit();

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

Stargazer 21.03.2011 17:18

Цитата:

Сообщение от arkadattx (Сообщение 982444)
Александр Мостовой, Stargazer, спасибо за мнение, но хотелось бы больше конкретики и объективизма.

Я уже выдал максимум конкретики: общий для всех обработчик - это искусственная конструкция. Для неё нет никаких причин, кроме лени разработчика написать несколько лишних строк.

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

Вернёмся к вашей ситуации.
Совершенно классическая ситуация "событие-обработчик". Событие - это один элемент. Обработчик - это другой элемент. Логика подсказывает, что самым логичным будет просто напрямую связать один элемент с другим, ведь больше ничего и не нужно? Таким образом, связи в программе будут простыми и легко читаемыми: closeButtonClickHandler, settingsButtonClickHandler, ... и т.д. Всё просто и чётко. Мне нужно только ткнуть на имя функции в outline в FD и работать. Да и просто беглый взгляд по outline помогает тут же определить, чем занимается данный класс.

Вы же для чего-то хотите ввести дополнительный элемент, с целью сперва обобщить те вещи, у которых нет ничего общего (!), а потом разгородить всё обратно при помощи case. То есть вы выполняете 2 противоположных действия - ради чего? Назовите хоть 1 архитектурный плюс данного решения (аргумент "мне лень написать лишний раз addEventListener" не принимается).

В архитектуре мы видим очевидный минус: этот убер-обработчик имеет слишком ниточек, тянущихся к другим элементам системы. Если вы хотите добавить новый обработчик - вместо того, чтобы прописать ещё 1 функцию и сохранить код в чистоте - вы будете добавлять новый case с новым алгоритмом и каждый следующий case будет смотреться ещё более невыносимо, чем предыдущий, число ниточек будет расти и в итоге ваш обработчик окончательно превратится в помойку (чем он и был с самого начала, на самом деле). И вообще, если в case выполняется более 2 команд - то всё равно нужно делать отдельную функцию. При таком подходе вообще неясно на чём вы сэкономили.

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

Резюмируем:
-: логически не обосновано
-: читать неудобно
-: делает систему менее гибкой

+: ???

carrotoff 21.03.2011 20:56

Думаю не стоит использовать кейсы, ибо код становится нагроможденным и нечитабельным.
Особенно, в том случае если обработчики для ваших кейсов будут представлять собой не одну строку, как в примере (exit(), text(1), test(-1)), а целую конструкцию, и получится просто жесть типа

Код AS3:

private function onMouseEvent(e:MouseEvent):void
{
        if (e.target is ISkinButton)
        {
                switch (e.target.name)
                {
                        case "closeButton":
                        case "exitButton":
                        function(){
                          if(a == b){
                            while(x < arr.length){
                            // .........
                            }
                          }
                        }
                        break;
                        case "plusButton":
                        text(1);
                        break;
                        case "minusButton":
                        test( -1);
                        break;
                }
        }
}

Ну можно усложнять и усложнять..

Psycho Tiger 21.03.2011 21:38

Ранее ратовал за switch/case. Ныне вдохновившись речами wxvxw и собственным опытом ратую против них в подобных конструкциях.


Часовой пояс GMT +4, время: 09:11.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.