Jak można identyfikować obiekty?

  1. Można przechowywać wskaźniki / referencje do nich;
  2. Można przechowywać obiekty w jakiejś tablicy lub słowniku i przechowywać ich indeksy czy innego rodzaju idki.

Do niedawna sądziłem, że preferowane podejście to to pierwsze.

Ale ostatnio czytam, że raczej jednak to drugie, gdyż: (a) jest ono w zasadzie jedynym sensownym, jeśli chce się trzymać paradygmatu funkcyjnego, który obecnie ludzie chwalą; (b) Umożliwia bezbolesną serializację i deserializację danych; (c) inne?

Co ja robię w tej mojej nieszczęsnej gierce, którą mam nadzieję jednak w końcu ukończyć?

  • Backend stosuje to pierwsze podejście, i to ostro. W konsekwencji potrzebny jest dodatkowy kod, by móc serializować dane przy przesyłaniu ich do klienta. W konsekwencji także nie mogę bezboleśnie po prostu zserializować stanu gry do bazy danych, co mi doradzano. Tzn. mogę zapisywać do bazy danych replay'e, ale na to jest osobny kod i te informacje nie starczą na pełne odtworzenie stanu gry; natomiast pełna serializacja stanu wymagałaby przestudiowania całego obecnego kodu i sporo pracy.
  • Frontend stosuje to drugie podejście. Dlaczego? Nie chciało mi się pisać kodu zmieniającego idki na referencje po otrzymaniu zserializowanych danych od serwera.

Niestety to drugie podejście prowadzi do kwiatków tego rodzaju:

for (let i = 0; i < monsAndMoves.mons[monname].moves.length; i++) {
  for (let j = 0; j < monsAndMoves.moves[monsAndMoves.mons[monname].moves[i]].prerequisites.length; j++) {
    g.setEdge(monsAndMoves.moves[monsAndMoves.mons[monname].moves[i]].prerequisites[j], monsAndMoves.mons[monname].moves[i], {
      /*...*/
    })
  }
}

Co się tu stało?

  • monsAndMoves - obiekt przechowujący informacje o wszystkich ciosach i gatunkach potworków
  • monsAndMoves.moves - tablica przyporządkowująca indeksom informacje o ciosach (powinien być słownik mapujący nazwy na ciosy by zachować spójność z poniższym)
  • monsAndMoves.mons - słownik przyporządkowujący nazwom gatunków stworków informacje o tych gatunkach
  • monname - powinno nazywać się currentMon.speciesName - id gatunku obecnego stworka
  • prerequisites - idki ciosów, które stworek musi znać, by nauczyć się obecnego ciosu

Gdybym trzymał referencje zamiast idków, to po jeszcze paru mniej znaczących ulepszeniach powyższy kod wyglądałby zapewne tak...:

for (const move of currentMon.species.moves) {
  for (const prereq of move.prerequisites) {
    g.setEdge(prereq.name, move.name, {
        /* ... */
    })
  }
}

Postęp chyba wyraźny??? (Dlatego właśnie trzymanie idków a nie referencji uważałem za jeden z objawów tragicznej jakości kodu frontu)

Czy jest możliwość zrobienia tak, by wilk był syty i owca cała, tj. by zachować korzyści płynące z trzymania idków miast wskaźników lub referencji, ale jednocześnie nie prowadzić do nieczytelnego kodu, jak powyżej?

EDIT: Tj oczywiście można tak:

const currentSpecies = monsAndMoves.mons[currentMon]
const moves = currentSpecies.moves
for (const moveName in moves) {
  const move = moves[moveName]
  for (const prereqName in move.prerequisites) {
    g.setEdge(moveName, prereqName, {
      /* ... */
    })
  }
}

Problem polega na tym, że wtedy pierwsze 2 linijki powyższego snippetu w zasadzie trzeba powtarzać na początku każdej jednej funkcji... A to staje się upierdliwe szczególnie, jeśli (a to podejście znowu się chwali) funkcje mają być jak najmniejsze, a za to liczne.