niedziela, 27 lipca 2014

Rozszerzenia do "Coderetreat" i "Game of Life"

Global Day of Coderetreat stanowi niesamowitą pomoc w sianiu eksplozji wiedzy w kierunku jednostek programistycznych wciąż uwięzionych w rozwiązywaniu problemów programistycznych przy pomocy tandemu for-if (powtórz n razy). Aby było łatwiej zachęcić ludzi do udziału wydarzenie odbywa się w porze roku kiedy najłatwiej odpalić samochód a wszyscy są opaleni i wypoczęci - czyli na przełomie listopada i grudnia.

Aby nie robić kolejnego CRUDa pracujemy z ciekawszym problemem czyli Grą w życie (nie mylić z "grą życie", którą uprawiamy na codzień). I chociaż ludzie czasem narzakają, że ciągle jest to samo ćwiczenie i można by wrzucić coś nowego to jednak co roku scenariusz przebiegu zdarzeń mówi co innego.

Najpierw większość ludzi jedzie proste rozwiązanie z tablicą dwu wymiarową i wali w komórki albo booleany albo inty. Później mamy trudną do przetestowania gigantyczną metodę main lub kilka mniejszych metod z (niestety) wszędzie rozsianymi iteracjami po tablicach. To czego przez ostatnie dwa lata prowadzenia coderetreat nie udało mi się wyjaśnić to to to to, że rozwiązanie samo w sobie nie jest istotne - właśnie dlatego je wywalamy na końcu (oj jak tego ludzie nie lubią!).

Ważna jest obserwacja, ważny jest proces nauki, ważne jest wyciągnięcie wniosku i zrozumienie jak dana decyzja wpływa na całokształt rozwiązania i dalsze decyzje. Np. fajne byłoby olśnienie, że jeśli każde miejsce kodu jest świadome tego, że operujemy na tablicy dwuwymiarowej to jakakolwiek próba zmiany tego konkretnego aspektu będzie boleć.

Poza Object Calisthenics

Object Calisthenics(link) to zbiór ciekawych ograniczeń, których nazwy nich*ja nie mogę zapamiętać. Ograniczeń - bo formuła ćwiczeń jest dosyć ciekawa - zamiast narzucać (no dobra trochę się narzuca), że dane rozwiązanie jest lepsze - staramy się zaprogramować rozwiązanie z ograniczeniem np."metody maks 5 linii" i pomóc uczestnikom ćwiczeń samemu wyciągnąć wnioski.

Do niedawna Object Calisthenics to była taka obiektowa nirwana ale ale jak już i w javie pojawiły się "strzałki" to warto zerknąć na inne nirwany i zapoznać się z mechanizmami, których w javie do tej pory nie było albo jeszcze nie ma.

Wyrzucić długopisy i ołówki

... i przesiąść się do painta (nie nie to tylko żart prowadzącego).

Generalnie wiele zespołów na początku dużo dyskutuje o rozwiązaniach i nic a nic nie koduje :( i chyba dlatego wymyśloną sesję "nic nie gadamy tylko piszemy". A można zacząć inaczej. Zastanówmy się co jest potrzebne na samiutkim początku? Mamy komórki i jest też jakaś plansza. I tyle wystarczy by zacząć

trait GameOfLifeBlueprint{
 type Board
 type Cell
}

Słówko "type" należy czytać "jest sobie jakiś typ" (w sensie abstrakcyjnym a nie w sensie "patrz na niego ale typ"). I tyle - decyzje co to będzie za typ odkładamy na później...

I tak dalej

No dobra komórki są gdzieś położone na planszy. Przydałoby się je jakoś namierzyć

trait GameOfLifeWithCoordinates extends GameOfLifeBlueprint{
 type Coordinates
 def findCell(c:Coordinates)(implicit b:Board):Cell
}

I już mamy planszę, komórki i współrzędne a cały czas nie wiadomo co tam siedzi - i to jest poniekąd dobre bo mamy wciąż swobodę podejmowania decyzji. No i podejmujemy decyzje. Zamiast bawić się z tablicami przestrzeń za symuluje nam mapa. Kto chce 2D ma 2D a kto DDD ten ma 3D.

trait MapBasedGame extends GameOfLifeWithCoordinates{
 type Board=Map[Coordinates,Cell]
 val board:Board=Map[Coordinates,Cell]()
}

trait GameOfLife2D extends MapBasedGame{
 type Coordinates=(Int,Int)
}

trait GameOfLife3D extends MapBasedGame{
 type Coordinates=(Int,Int,Int)
}

To co jest jeszcze nie określone to Cell - no to wio

trait GameOfLifeWithStandardCells extends GameOfLifeWithCoordinates{
 trait GameCell
 case class LiveCell() extends GameCell
 case class DeadCell() extends GameCell
 type Cell=GameCell
 implicit val board:Board

 def lifeNeighbours(c:Coordinates)(implicit b:Board):Int
 
 def evolve(c:Coordinates):Cell=(findCell(c),lifeNeighbours(c)) match {
  case (DeadCell(),3)=>LiveCell()
  case (LiveCell(),2)=>LiveCell()
  case (LiveCell(),3)=>LiveCell()
  case _ => DeadCell()
 }
}

Przydałoby się ogarnąć jakieś zalecenia co i w jakiej kolejności zaleca się deklarować. W każdym razie powstało coś na wzór Metody Szablonowej także jak ktoś chce jakies wzorce projektowe to je ma.

No to gramy...

...ale jeszcze nie teraz bo nie chce psuć zabawy uczestnikom (a tak naprawdę nie chce mi się tego implementować bo jeszcze muszę dzisiaj spodnie sobie wyprasować). W każdym razie będzie to mniej więcej wyglądało tak :

object NormalGame extends GameOfLife2D with GameOfLifeWithStandardCells{
 def lifeNeighbours(c:Coordinates)(implicit b:Board):Int={...}
 def findCell(c:Coordinates)(implicit b:Board):Cell={...}
}

A Jak chcemy mieć więcej komórek to też łatwo idzie :

trait GameOfLifeWithZombieCells extends GameOfLifeWithStandardCells{
 case class ZombieCell() extends GameCell
 def zombieNeighbours(c:Coordinates)(implicit b:Board):Int
 
 override def evolve(c:Coordinates):Cell=(findCell(c),lifeNeighbours(c),zombieNeighbours(c)) match {
  case (DeadCell(),3,3)=>ZombieCell()
  case (LiveCell(),2,2)=>ZombieCell()
  case (LiveCell(),3,_)=>LiveCell()
  case _ => DeadCell()
 }
}

object ZombieGame3D extends GameOfLife3D with GameOfLifeWithZombieCells{
 def lifeNeighbours(c:Coordinates)(implicit b:Board):Int={...}
 def findCell(c:Coordinates)(implicit b:Board):Cell={...}
 def zombieNeighbours(c:Coordinates)(implicit b:Board):Int={...}
}

Jakie ograniczenie?

No i cała magia coderetreat polega na tym aby za bardzo nie wchodzić w teorię ale by dać ograniczenie i pozwolić każdemu na własne skórze odczuć uwagi i wnioski. Tutaj można dać "wszystkie typy abstrakcyjne" albo "jeden typ abstrakcyjny na trait" ale to na razie jest jedna wielka improwizacja z mojej strony także zobaczymy co przyszłość przyniesie.

Z kronik "Maintenance City"

Przypomniało mi się zabawne zdarzenie z 2011 kiedy jeszcze nie prowadziłem a tylko uczestniczyłem w CR. Siedzimy sobie i robimy pair programming no i nagle koleś się zawiesza. Pytam "co się dzieje" a ten prawie ze łzami w oczach "o kurde od roku chyba nie robiłem nowej klasy w Eclipse". No to pozdrowienia dla wszystkich we wspólnej walce na awans z low cost centre utopia na to co tam jest następne.

Brak komentarzy:

Prześlij komentarz