View Full Version : [Importante] Refactoring di BigGem / Droppable & co.
Portiamo alla luce alcune questioni che riguardano questo importantissimo refactoring:
Il nostro obiettivo è quello di far sparire la differenziazione dei comportamenti di Grid/GridController nei confronti di BigGem ed i vari Droppable.
Il problema nasce dal fatto che è un refactoring più grosso del previsto in quanto richiede il cambiamento di molte parti del codice (Grid, GridController, BigGem, le varie DroppableAction e gli State) che non è semplice da eseguire a piccoli passi e la scorsa settimana mi sono ritrovato a tentare alcune strade per poi revertare quando mi accorgevo che prima bisognava essere fatto qualcos'altro.
La strada che attualmente ho scelto è quella di eliminare ogni riferimento a Gem all'interno di BigGem.
Ho notato che per fare ciò bisogna rivedere i comportamenti di canMoveDown e moveDown di BigGem. Qui si rivela un problema. Il comportamento di canMoveDown e moveDown di Droppable non è per niente chiaro e nonostante qualche refactoring ancora ci da dei problemi:
Innanzitutto Droppable non deve dipendere dalla posizione della Sprite (pixel) nello schermo e dalla posizione della griglia (sempre pixel) per determinare se ci si può muovere verso il basso. Questo comportamento va assolutamente chiarito perchè in BigGem non vorrei riprodurre comportamenti ambigui che darebbero problemi in futuro.
Il cuore del problema risiede nel fatto che gli oggetti si muovono non solo a livello di "cella" ma anche a livello di "pixel" durante la caduta e questa gestione deve essere indipendente da Sprite.
Se avete proposte in merito sarò lieto di valutarle :)
Siccome ho ci ho lavotarato un po' sopra dico le mie idee. :sofico:
Partiamo da un assunto: qualunque tipo di gravità, che rappresente il valore di spostamente verticale, è sempre MINORE della grandezza verticale della cella.
Ora si possono presentare 3 casi:
1) la gemma non si può muovere
2) la gemma può cadere e può muoversi dell'interà gravità senza collidere
3) la gemma può cadere ma non può muoversi dell'intera gravità perchè colliderebbe prima.
Dunque canMoveDown ritorna false nel caso 1 e true nel caso 2 e 3.
MoveDown opera solo nei casi 2 e 3, quindi controlla prima canMoveDown.
Se 2 aggiorna la posizione muovendo dell'intera gravità, altrimenti se 3 si allinea la gemma alla riga.
A questo punto sdi ricontrolla canMoveDown e se è passato a false si fa drop.
Fin qua direi che è semplice... :D
Ora ci sono due questioni:
a) come calcolare l'offset rispetto alla cella.
b) aggironare la cella capendo che la gemma ha cambiato riga.
Fino ad ora direi che il cambio di riga è stato determinato nel momento in cui la gemma supera il bordo inferiore della cella corrente o, in altre parole, quando entra nel bordo superiore della cella sottostante. In tal caso vienbe aggiornato il valore della cella.
Io manterrei l'offset coerente con questa informazione. Quindi offset=0 implica gemma allineata alla cella. Quindi obbligattoriamente l'offset si calcolerebbe tra il bordo superiore della cella e della gemma. In tal modo l'offset si comporta in questo modo:
0: allineta
31: entrata in una nuova riga (Cell.SIZE = 32)
30
29
....
....
1
0: allineata nuovamente
Tuttto chiaro?? :cool:
Ora è indubbio che la determinazione del cambio di riga può essere fatto in modo diverso, basta che sia mantenuto coerentemente nel codice, come ad esempio considerare il cambio di riga solo ad allienamento concluso.
Ora le lamentele.
Devo dire che a sto giro i test stanno aiutando molto poco :mad:
Molto probabilmente per un problema che avevo già sollevato relativamente agli update: praticamente ogni test usa un numero di update empirico, calcolato per tentativi, in modo che il test abbia il comportamento corretto...e non fraintendetemi, non sto dicendo che sia stato fatto il codice prima del test.
Questo fa si che molti test non siano chiarissimi o che definiscano esattamente che cosa volevano testare.
Ok...direi che ho detto :D :D
Altra cosa....propongo un direttore d'orchestra per questo refactoring.
E' molto complesso e avere un supervisore attivo al refactoring mi sembrerebbe un ottima idea.
Io propongo Ufo perchè è oltre una settimana che ci sta sopra e ormai ha un quadro sufficentemente ampio. ;)
Altra cosa....propongo un direttore d'orchestra per questo refactoring.
E' molto complesso e avere un supervisore attivo al refactoring mi sembrerebbe un ottima idea.
Io propongo Ufo perchè è oltre una settimana che ci sta sopra e ormai ha un quadro sufficentemente ampio. ;)
E l'orchestra? :D
E l'orchestra? :D
Se vuoi io faccio il triangolo :rotfl: :rotfl: :rotfl:
cdimauro
07-06-2006, 14:30
Adesso vi dico la mia da niubbone che ha appena finito di visionare tutti i sorgenti legati a Gem, BigGem, Grid, ecc. ecc. e che per questo è ancora in stato confusionale :D: non sarebbe il caso che Grid gestisse tutti gli oggetti in maniera "uniforme"?
Con ciò intendo: avere a che fare con UN UNICO tipo base per gli oggetti, che poi sono specializzati e si comportano in modo diverso a seconda dell'implementazione.
Quindi Gem, BigGem, Chest, ecc. ma anche la stessa GemsPair dal punto di vista di Grid dovrebbero essere oggetti (di dimensione arbitraria) che si muovono e cadono oppure si sono fermati in fondo alla griglia, e che "interagiscono" con la griglia e con gli altri oggetti eventualmente in essa presenti.
Interazione vuol dire che il loro stato e quello degli oggetti con cui interagiscono può cambiare.
E' troppo sempliciotto come discorso, vero? :angel:
Ehi, tu, ti ho visto, sai: metti giù quella mazza!!! :D :D :D
jappilas
07-06-2006, 14:37
Adesso vi dico la mia da niubbone che ha appena finito di visionare tutti i sorgenti legati a Gem, BigGem, Grid, ecc. ecc. e che per questo è ancora in stato confusionale :D: non sarebbe il caso che Grid gestisse tutti gli oggetti in maniera "uniforme"?
...
E' troppo sempliciotto come discorso, vero? :angel:
veramente, no
dal mio pdv anzi è quello che mi aspettavo diamonds già facesse prima di vedere il codice effettivamente implementato ;)
ps: composite + delegation ? :stordita:
cdimauro
07-06-2006, 15:03
veramente, no
dal mio pdv anzi è quello che mi aspettavo diamonds già facesse prima di vedere il codice effettivamente implementato ;)
Idem: adoro la semplicità. :p
ps: composite + delegation ? :stordita:
Se serve a semplificare tutto e a renderci la vita più facile, perché no?
:sofico:
Adesso vi dico la mia da niubbone che ha appena finito di visionare tutti i sorgenti legati a Gem, BigGem, Grid, ecc. ecc. e che per questo è ancora in stato confusionale :D: non sarebbe il caso che Grid gestisse tutti gli oggetti in maniera "uniforme"?
Con ciò intendo: avere a che fare con UN UNICO tipo base per gli oggetti, che poi sono specializzati e si comportano in modo diverso a seconda dell'implementazione.
Quindi Gem, BigGem, Chest, ecc. ma anche la stessa GemsPair dal punto di vista di Grid dovrebbero essere oggetti (di dimensione arbitraria) che si muovono e cadono oppure si sono fermati in fondo alla griglia, e che "interagiscono" con la griglia e con gli altri oggetti eventualmente in essa presenti.
Interazione vuol dire che il loro stato e quello degli oggetti con cui interagiscono può cambiare.
E' troppo sempliciotto come discorso, vero? :angel:
Ehi, tu, ti ho visto, sai: metti giù quella mazza!!! :D :D :D
L'idea è stata sin dall'inizio quella ;)
Figuratevi che il moveDown delle AbstractdDroppable lo faceva grid...quindi altro che omogeneità di gestione :(
L'idea che esponi è esattamente quello a cui dobbiamo arrivare, già fek in un precedente post ha sottolineato come le action siano da considerasi azioni che modificano lo stato della griglia e, perchè no, queste chiedano ai singoli oggetti dimofiicare il loro stato ;)
Il problema è arrivarci a quel punto considerando che il codice rema al contrario :cry:
cdimauro
07-06-2006, 15:38
Infatti: il mal di testa dovuto alla lettura del codice mi si trascina ancora... :cry:
Vediamo di arrivarci, anche se so bene che sarà un'impresa titanica.
Continuo a sbatterci la testa per cercare di capire DA DOVE si potrebbe iniziare... :p
allora, io sono sempre alle prese con il refactoring di AbstractDroppable, in modo che si usi un sistema di coordinate relative alla riga della droppable, in particolare l'idea proposta da Ufo era quella di mantenere un yOffsetByCell che mantenessel'offset tra il bottom della droppable ed il top della cella (può essere un po contorto, ma è il valore che rende più semplice tutto il lavoro di controllo di canMoveDown, e cambio di riga in moveDown)...introducendo questo refactoring abbiamo avuto il problema che in pratica nella gemsPair la gemma sopra, usando il metodo isCellBelowFull di grid, si droppava perchè rilevala che l'altra gemma della pair occupava la cella sotto, allora Bonfo ha proposto di controllare anche se la gemma che occupi la cella sotto sia dropped....ho seguito questa strada, ho dovuto modificare qualche test, ma mi sono trovato di fronte ad un unico test che non passa relativo alle caduta di una bigGem dopo un crush (testBigGemFallingWithGravityToGridBottom) ...ora devo sospendere il lavoro, mi sembrava che le gemme, dopo una crush, cadessero da dropped, e mi sembra strano che sia solo un test a non passare...cosa ne pensate!?
cdimauro
08-06-2006, 08:06
introducendo questo refactoring abbiamo avuto il problema che in pratica nella gemsPair la gemma sopra, usando il metodo isCellBelowFull di grid, si droppava perchè rilevala che l'altra gemma della pair occupava la cella sotto, allora Bonfo ha proposto di controllare anche se la gemma che occupi la cella sotto sia dropped....ho seguito questa strada, ho dovuto modificare qualche test, ma mi sono trovato di fronte ad un unico test che non passa relativo alle caduta di una bigGem dopo un crush (testBigGemFallingWithGravityToGridBottom) ...ora devo sospendere il lavoro, mi sembrava che le gemme, dopo una crush, cadessero da dropped, e mi sembra strano che sia solo un test a non passare...cosa ne pensate!?
Penso che col modello che ho esposto questo problema sparirebbe del tutto, perché la GemsPair diventerebbe un'oggetto a sé stante ed è in quanto tale che "interagirebbe" con la griglia e gli altri oggetti (Gem, BigGem, ecc.).
Le due gemme di cui è composta, insomma, sono un dettaglio puramente interno e che NON dev'essere noto agli altri.
Soltanto gli effetti delle interazioni sono importanti, ed è solo in questo caso che le due "gemme" di cui è composta una GemsPair incideranno nei cambiamenti di stato di oggetti e griglia.
Interessante. Quindi anche GemsPair dovrebbe implementare Droppable...
... MI PIACE !!! :D :D
cdimauro
08-06-2006, 12:23
Certamente. In questo modo si uniformerebbe la gestione di QUALUNQUE oggetto che Grid deve gestire, presente e futuro.
L'unica cosa che cambia è la diversa "reazione" di un oggetto quando viene a contatto con un altro oggetto oppure col fondo della griglia. ;)
Adesso vi dico la mia da niubbone che ha appena finito di visionare tutti i sorgenti legati a Gem, BigGem, Grid, ecc. ecc. e che per questo è ancora in stato confusionale :D: non sarebbe il caso che Grid gestisse tutti gli oggetti in maniera "uniforme"?
Con ciò intendo: avere a che fare con UN UNICO tipo base per gli oggetti, che poi sono specializzati e si comportano in modo diverso a seconda dell'implementazione.
Quindi Gem, BigGem, Chest, ecc. ma anche la stessa GemsPair dal punto di vista di Grid dovrebbero essere oggetti (di dimensione arbitraria) che si muovono e cadono oppure si sono fermati in fondo alla griglia, e che "interagiscono" con la griglia e con gli altri oggetti eventualmente in essa presenti.
Interazione vuol dire che il loro stato e quello degli oggetti con cui interagiscono può cambiare.
E' troppo sempliciotto come discorso, vero? :angel:
Ehi, tu, ti ho visto, sai: metti giù quella mazza!!! :D :D :D
Hai azzeccato in pieno l'obbiettivo finale di questo refactoring
Interessante. Quindi anche GemsPair dovrebbe implementare Droppable...
... MI PIACE !!! :D :D
A mio parere ora abbiamo la priorità di eliminare la BigGemList da Grid. Per fare ciò BigGem deve diventare indipendente da Droppable prima di tutto.
Inoltre non devono più esistere in Grid le Gem che costituiscono una BigGem, nel momento in cui vengono assorbite da una BigGem devono essere eliminate :)
Certo...è quello l'obbiettivo. :D
Il problema è che se implementiamo il moveDown di AbstractDroppable come se fosse "sola" succede quello che diceva daniele....e quindi test rossi :(
Bisogna implementare per ogni tipo, cioè BigGem, AbstractDroppable e GemsPair, il moveDown attraverso varie iterazioni su per cercare di disaccoppiarli sempre un po' di più ad ogni iterazione...altrimenti ci scordiamo i test verdi per un bel po' :(
cdimauro
09-06-2006, 07:56
Ragazzi, è un vero casino. :(
Vi faccio la proposta indecente di cui ho già parlato con Federico ieri sera.
Per arrivare alla soluzione del problema ci sono 3 strade:
1) buttare tutto ciò che riguarda Gem, BigGem, ecc. e ricominciare da capo;
2) rifattorizzare a forza finché non si raggiunge l'obiettivo;
3) sviluppare le nuove classi parallelemente a quelle esistenti, trasferendo man mano le competenze di queste ultime.
La 1), anche se la preferirei (quando il codice è troppo incasinato preferisco buttare tutto, fermarmi a riflettere, e "rebuild from scratch"), è da scartare, perché ci bloccherebbe e noi siamo già troppo indietro con lo sviluppo.
La 2) è quella che stiamo seguendo adesso, e che ci sta facendo perdere parecchio tempo.
La 3) è la mia proposta. Si può benissimo andare avanti con le storie, finché non ci sarà il "passaggio di consegne" fra vecchie e nuove classi. Inoltre ci permette di testare il funzionamento delle vecchie e delle nuove classi, per vedere se ci sono "deviazioni" dal contratto / requisiti stabilito ("Quante deviazioni hai... Dimmi che non ne hai!" - Vasco :D).
OK, lo so: mi sono scavato la fossa con le mie mani. E' stata una vita breve, ma intensa. :p
Comunque oggi continuo a studiarmi i sorgenti, ma da domani e fino a martedì non ci sarò (sono a Roma, e senza PC. :cry: ).
Cerchiamo di definire bene il da farsi. Sono convintissimo che, una volta raggiunto l'obiettivo, avremo la strada spianata e potremo andare avanti molto più velocemente.
Investire oggi per guadagnare domani (lo so, è YAGNI, ma abbassate la baionette!!! :D).
La 1), anche se la preferirei (quando il codice è troppo incasinato preferisco buttare tutto, fermarmi a riflettere, e "rebuild from scratch"), è da scartare, perché ci bloccherebbe e noi siamo già troppo indietro con lo sviluppo.
È anche la mia preferita. Questo è uno dei rari casi una approccio top-down classico è più conveniente. Abbiamo le specifiche chiare ed immutabili nei test. Penso che con un paio di persone full-time e una settimana a lavorarci in un branch separato sarebbe possibile completare la riscrittura. Il problema è che togliendo un paio di persone dai task normali dimezziamo quasi il team di sviluppo quindi non praticabile con le nostre risorse.
La 2) è quella che stiamo seguendo adesso, e che ci sta facendo perdere parecchio tempo.
Abbiamo già appurato che è poco efficace. :muro:
La 3) è la mia proposta. Si può benissimo andare avanti con le storie, finché non ci sarà il "passaggio di consegne" fra vecchie e nuove classi. Inoltre ci permette di testare il funzionamento delle vecchie e delle nuove classi, per vedere se ci sono "deviazioni" dal contratto / requisiti stabilito ("Quante deviazioni hai... Dimmi che non ne hai!" - Vasco :D).
Possiamo provare. :)
ciao ;)
Investire oggi per guadagnare domani (lo so, è YAGNI, ma abbassate la baionette!!! :D). veramente non è YAGNI... :p
cdimauro
09-06-2006, 09:50
:)
Bene, a questo punto decidiamo se optare per la 1) / Branch o per la 3) / trunk.
Purtroppo so che la forza lavoro scarseggia di questi tempi, ma non possiamo farci niente. Magari, così facendo, riusciamo a recuperare tempo per qualche feature che è stata tagliata: col codice più semplice e comprensibile si lavora tutti meglio, e anche gente che vuole avvicinarsi al progetto non si troverà a dover sbattere la testa contro un muro per capire come funziona il codice.
EDIT: Alberto, hai la firma irregolare! :asd: :asd: :asd:
..già :(
Purtroppo lo sviluppo va a rilento anche perchè gestire il codice è attualmente un'impresa.
Io voto per la 3 :D
Abbiamo un più stretto contatto con le specifiche e appena le "nuove" features del codice sono disponibili possono essere da subito usati nel resto del progetto, senza dover aspettare il merge con un eventuale branch.
3) sviluppare le nuove classi parallelemente a quelle esistenti, trasferendo man mano le competenze di queste ultime.
Lo abbiamo fatto con BigGem io e Federico e spesso funziona bene. Vai pure nel trunk.
cdimauro
09-06-2006, 16:13
Io domani parto per Roma e rientro martedì sera, quindi non posso farlo (sono senza PC e connesione a internet :(). Se ne parla mercoledì.
Io domani parto per Roma e rientro martedì sera, quindi non posso farlo (sono senza PC e connesione a internet :(). Se ne parla mercoledì.
Acc... :(
Anch'io sono messo malissimo: sono sotto con lo studio fino a giovedì.
E' già tanto se ho tempo di respirare... :cry: :cry:
In ogni caso venerdì, per festeggiare ( :sperem: ), lavoro su Diamonds :D :D
Io domani parto per Roma e rientro martedì sera, quindi non posso farlo (sono senza PC e connesione a internet :(). Se ne parla mercoledì.
Buon viaggio ;)
Ho provato a togliere la DroppableList da BigGem.
I problemi sono principalmente 3:
- Draw()
- MoveDown()
- CanMoveDown()
Quindi:
- bisogna fare una TiledSprite come detto da Ufo
- Bisogna gestire la posizione delle BigGem anche qui con un offset rispetto all'allineamento alla row
Ora vi abbandono per qualche giorno...l'esame è alle porte :cry:
sto procedendo con il refactoring di BigGem eliminando qualunque riferimento a Gem all'interno della stessa.
Purtroppo tale refactoring richiede addirittura la modifica di un po' di test sul draw delle BigGem che non erano stati ben impostati (colpa mia :P)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.