![]() |
|
||||||||||
|
|||||||
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | Опции просмотра |
|
![]() |
![]() |
|
|
|
|||||
|
Modus ponens
|
Switch сам по себе не плохой, но почему-то всегда, когда я с ним сталкиваюсь, он не там, где нужно... И это потому, что switch имеет тенденцию повторятся (т.е. если вы видите, что вы делаете свитч по значениям того же энумератора дважды и более раз, или просто по тем же значениям - you are doing it wrong!). Т.е. вы скопипастили какую-то логику, и вы за это поплатитесь, потому, что природа не терпит повторений, и стремится все ее части сделать уникальными
Если в switch'е, в каком-нибудь кейсе есть более одной строчки, через месяц там будет красоваться if, а через два логика програмы будет на столько испохаблена, что разобраться почему там теперь вложенный switch уже не реально. Switch располагает к созданию фиктивных конструкций, часто нужных только для того, чтобы switch работал, что, естественно загромождает и замусоривает код. В большинстве случаев кейсы можно вынести во внешние файлы настроек или заменить нормальными методами. Кроме того, иногда switch используется для хранения состояния приложения - за это природа не просто наказывает... за ней еще и суд присяжных может следом добавить... Т.е. для создания супер-надежных программ switch очень плохой помощник. Если вы использовали его вместо того, чтобы создать state и описать в нем, что делает программа при определенных обсоятельствах - не дай бог вам программировать ПО для хирургии... потом к компутеру будет страшно подойти (непридуманная история).
__________________
Hell is the possibility of sanity |
|
|||||
public class ChatBubbleIngame extends ChatBubble { /** * Chat Bubble with positions * @param host * @param seat * @param maxPlayers */ public function ChatBubbleIngame(host:DisplayObjectContainer, seat:int, maxPlayers:int) { super(host); if (maxPlayers === 6) { switch (seat) { case 0: setTailPosition(2); break; case 1: setTailPosition(3); break; case 2: case 3: case 4: setTailPosition(0); break; case 5: setTailPosition(1); break; default: throw new ArgumentError(seat); break; } } else { switch (seat) { case 0: setTailPosition(2); break; case 1: case 2: setTailPosition(3); break; case 3: case 4: case 5: case 6: setTailPosition(0); break; case 7: case 8: setTailPosition(1); break; default: throw new ArgumentError(seat); break; } } } override public function setTailPosition(tailPosition:int):void { switch (tailPosition) { case 0: _gfx.x = -2; _gfx.y = -54; break; case 1: _gfx.x = -5; _gfx.y = 57; break; case 2: _gfx.x = - 5; _gfx.y = 57; break; case 3: _gfx.x = 2; _gfx.y = -54; break; } super.setTailPosition(tailPosition); } }
__________________
Тут мужик танцует и поёт про флэш |
|
|||||
|
Регистрация: Dec 2010
Адрес: Химки МО
Сообщений: 95
|
public class ChatBubbleIngame extends ChatBubble { /** * Chat Bubble with positions * @param host * @param seat * @param maxPlayers */ public function ChatBubbleIngame(host:DisplayObjectContainer, seat:uint, maxPlayers:uint) { super(host); var arr:Array = maxPlayers === 6 ? [2,3,0,0,0,1] : [2,3,3,0,0,0,0,1]; if (seat >= arr.lenght) throw new ArgumentError(seat); else setTailPosition(arr[seat]) } override public function setTailPosition(tailPosition:uint):void { _gfx.x, _gfx.y = *([[-2,-54], [-5,57], [-5,57], [2,-54] ][tailPosition]); super.setTailPosition(tailPosition); } } Добавлено через 8 минут Цитата:
|
|
|||||
|
Да, это понятно. Мне всегда было проще сначала мыслить на конкретике, а потом уходить в абстракцию )
Спасибо.
__________________
Тут мужик танцует и поёт про флэш |
|
|||||
|
Modus ponens
|
Я могу попробовать в двух словах описать общую стратегию...
Итак, для начала нужно понять, что функционал можно делегировать стейтам. Т.е. у нас есть в общем 4 стейта, каждый из них работает тогда когда есть определенное количество игроков / учасников чата. У каждого стейта есть метод setTailPosition унаследованый от общего предка. И тогда все вместе это выглядит как-то так: class State { protected var _chatBubble:ChatBubbleIngame; protected var _jumpTable:Vector.<Vector.<State>>; public function State(chatBubble:ChatBubbleIngame) { super(); this._chatBubble = chatBubble; } public function setTailPosition():void { } public function transition(seat:int, maxPlayers:int):void { this._chatBubble.currentState = this.getPlayersMap(maxPlayers)[seat]; } private function getPlayersMap(maxPlayers:int):Vector.<State> { if (!this._jumpTable) this.createJumptable(); return this._jumpTable[int(maxPlayers == 6)]; } // NOTE: this part would normally come from settings. // This one is here for illustration purposes only. private function createJumptable():void { this._jumpTable = new <Vector.<State>>[ new <State>[ this._chatBubble.state2, this._chatBubble.state3, this._chatBubble.state1, this._chatBubble.state1, this._chatBubble.state1, this._chatBubble.state2, ], new <State>[ this._chatBubble.state2, this._chatBubble.state3, this._chatBubble.state3, this._chatBubble.state1, this._chatBubble.state1, this._chatBubble.state1, this._chatBubble.state1, this._chatBubble.state2, this._chatBubble.state2, ]]; } } class State1 { public function State1(chatBubble:ChatBubbleIngame) { super(chatBubble); } public override function setTailPosition():void { this._chatBubble._gfx.x = -2; this._chatBubble._gfx.y = -54; } } class State2 { public function State2(chatBubble:ChatBubbleIngame) { super(chatBubble); } public override function setTailPosition():void { this._chatBubble._gfx.x = -5; this._chatBubble._gfx.y = 57; } } class State3 { public function State3(chatBubble:ChatBubbleIngame) { super(chatBubble); } public override function setTailPosition():void { this._chatBubble._gfx.x = 2; this._chatBubble._gfx.y = -54; } } class ChatBubbleIngame { public function set currentState(value:State):void { this._currentState = value; } public function get state1():State1 { return this._state1; } public function get state2():State1 { return this._state2; } public function get state3():State1 { return this._state3; } private var _state1:State1; private var _state2:State2; private var _state3:State3; private var _currentState:State; public function ChatBubbleIngame(host:DisplayObjectContainer, seat:int, maxPlayers:int) { super(host); this._state1 = new State1(this); this._state2 = new State2(this); this._state3 = new State3(this); this._currentState = this._state1; this._currentState.transition(seat, maxPlayers); this.setTailPosition(); } public function setTailPosition():void { this._currentState.setTailPosition(); } }
__________________
Hell is the possibility of sanity Последний раз редактировалось wvxvw; 01.03.2011 в 00:29. |
|
|||||
|
wvxvw, спасибо. Но это конечно жесть )
Немного напомнило статью "как правильно писать факториал".
__________________
Тут мужик танцует и поёт про флэш |
|
|||||
|
Цитата:
Здесь с тем же успехом можно было и switch-ом замепить состояния (т.к. все остается внутри - класс, один хрен, сам себя параметризует этими состояниями - что со вичом - что с вектором) Главное, только, чтобы свич был один, а не 10 похожих в 10-и функциях, т.е. сама по себе стратегия может и уместна. Всётки конструкция "this._jumpTable[int(maxPlayers == 6)]" очевидности коду не добавляет. Последний раз редактировалось expl; 01.03.2011 в 01:08. |
|
|||||
|
Modus ponens
|
Ну так конечно, я же почему сначала оговорился о энтерпрайз
Такой подход имеет смысл если от количества игроков / посадочных мест зависит больше функций. С другой стороны - в моем коде нет повторений, а это значит, что если завтра входные условия поменяются, то у меня шанс ошибиться меньше, чем у тебя, потому что функционал продублирован, и ты можешь забыть поменять его в другом месте. Вообще, с точки зрения энтерпрайз простительно писать больше кода, если это снизит риск / предотвратит повторение, т.как основная задача - надежность а не скорость или объем.expl: Фишка в том, что входящие данные тоже надо подготавливать... для этого и существуют инженеры, которые проектируют, как кому и чего передать. Я просто не знаю чем обусловлен такой расклад, вполне возможно, что эти данные можно было передать / подготовить по-другому. Нестыковка происходит потому, что числовое значение maxPlayers никогда не используется, и если это правда, что оно не используется, то было бы умесно передать Boolean (т.как нам больше-то и не нужно). Опять же, вполне возможно, что setTailPosition() - единственная функция которая зависит от того сколько посадочных мест имеется в наличии, тогда мое деление на стейты - плохое. Но, это опять же потому что я не знаю, на сколько важны данные полученные на входе.
__________________
Hell is the possibility of sanity Последний раз редактировалось wvxvw; 01.03.2011 в 01:24. |
|
|||||
|
Цитата:
Я понимаю, если бы этот вектор приходил в класс снаружи, а так - ни в том, ни в другом случае дублирования нет, или я чего-то не догоняю? Вообще да, внимательнее посмотрел - одним свичом тут может и не получиться. Теперь еще и комментарий прочитал :/ Цитата:
Последний раз редактировалось expl; 01.03.2011 в 01:28. |
|
|||||
|
Modus ponens
|
Свич то один: там не совсем в свиче фишка, там два кейса дублируют один другой
И я не знаю, это так by design, или совпадение.
__________________
Hell is the possibility of sanity |
![]() |
![]() |
Часовой пояс GMT +4, время: 05:50. |
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | |
| Опции просмотра | |
|
|