CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[TS-JS] Comment optimiser mes fonctions ?

sagemtek
sagemtek
Niveau 23
30 mars 2021 à 13:24:37

Pour amoureux du code uniquement, mon code n'est pas si difficile mais c'est dur à comprendre quand on l'a pas fait soit même. Néanmoins je vais tacher de vous expliquer en détail à quoi ça sert. :hap:

Concernant le projet dont est issu ces codes, il s'agit d'un petit jeu 2D PIXEL ART que je développe, et qui utilise la génération procédurale notamment grâce au système cellular automata (Jeu de la vie pour ceux qui connaissent). :oui:

Fonction Principale
https://pastebin.com/Ve3qpB1g

Classe Loader
https://pastebin.com/ekXzhg6W

Classe Container
https://pastebin.com/df1PebrB

Classe Random Map
https://pastebin.com/FthgyWbX

Si vous voyez des erreurs, des possibilités d'optimisation je prend tout, mon but est de devenir un très bon programmeur web et d'en faire mon métier, ça serait avec plaisir d'obtenir des critiques et des conseils. :ange:

Merci à ceux qui prendront leur temps d'analyser mon code :ange:

sagemtek
sagemtek
Niveau 23
30 mars 2021 à 13:30:38

Ah oui et voici le genre de map que ce code peut générer

https://image.noelshack.com/fichiers/2021/13/2/1617103741-gen1.png
https://image.noelshack.com/fichiers/2021/13/2/1617103741-gen2.png

Pour l'instant c'est pas terrible, mais c'est normal j'ai ajouté qu'une seul règle, au fur et à mesure je vais en ajouter d'autres.

wouh_pinaise_
wouh_pinaise_
Niveau 6
30 mars 2021 à 16:09:30

J'ai la flemme d'essayer de comprendre le code donc je vais juste donner mon avis sur la forme. :hap:

  • Toutes tes textures pourraient être sous la forme d'un tableau en constante et tu pourrais le parcourir pour charger les textures : soit il contiendrait un objet simple ({'Grass01': '/Assets/Grass/grass_01.png', ...'}), soit un nouvel objet texture (avec attributs name et path par ex) :
monTableau.forEach(texture => loader.addTexture(texture.name, texture.path));
  • Pour vérifier qu'un élément n'est pas undefined, tu peux faire une double négation pour vérifier que ce n'est pas null, undefined ou empty (sauf si tu souhaites avoir un comportement différent entre null et undefined par ex)
if (tile2 != undefined)

A remplacer par

if(!!tile2)
  • En javascript, on essaye de privilégier le typage fort : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality

Donc === plutôt que == (sauf pour des cas particuliers)

  • Si tu utilises typescript, il faut typer au maximum :)

Je ne sais pas ce que ça prend en entrée, mais par exemple pour ta méthode getTile, il faudrait plutôt que ça ressemble à ça :

private GetTile(xx: number, yy: number): Tile {

C'est plus lisible et plus maintenable pour quelqu'un qui reprend ton code, mais aussi si tu reviens dessus après plusieurs mois.

  • Petite optimisation pour cette même méthode getTile (à tester et définir les bon types comme indiqué ci-dessus)
private GetTile(xx, yy) {
    return this.Tiles.find(tile => tile.xx === xx && tile.yy === yy);
}
  • Concernant la méthode GetNeighbours, tu n'as pas besoin de créer de variable pour le tableau. Tu peux directement faire un return du tableau construit.
  • Tu ne l'utilises jamais, mais pour info il est possible d'utiliser ? sur tes objets

Par exemple imaginons que tile est nul et que tu fasses tile.yy --> tu vas avoir une erreur.
En faisant tile?.yy tu n'en auras plus, ça renverra juste undefined ou null.

sagemtek
sagemtek
Niveau 23
30 mars 2021 à 16:12:37

C'est une super réponse merci à toi, je vais fixer tout ça. :ange:

Pathos-II
Pathos-II
Niveau 22
30 mars 2021 à 16:57:27

remplace les vars par let et const.
Quand tu crées un objet en JS, si le nom de l'attribut que tu as choisi est le même que le nom de la variable que tu lui passes en valeur, alors tu peux simplement mettre directement la variable.
ex :


let x = 1
let myObj = {
   x
}

au lieu de :


let xx = 1
let myObj = {
   x: xx
}
sagemtek
sagemtek
Niveau 23
30 mars 2021 à 17:55:54

Le 30 mars 2021 à 17:49:06 Zsetea a écrit :
utilise des const à la place des let quand t'as pas besoin de muter une variable

J'ai souvent tendance à mettre des let ou var à chaque fois, mauvaise habitude de débutant. Je vais faire plus attention et mettre des const, par contre j'aurais voulu savoir pourquoi il ne faut pas utiliser forEach ? Je trouve ça plus ergonomique qu'une boucle for :(

Le 30 mars 2021 à 16:57:27 Pathos-II a écrit :
remplace les vars par let et const.
Quand tu crées un objet en JS, si le nom de l'attribut que tu as choisi est le même que le nom de la variable que tu lui passes en valeur, alors tu peux simplement mettre directement la variable.
ex :


let x = 1
let myObj = {
   x
}

au lieu de :


let xx = 1
let myObj = {
   x: xx
}

Je savais pas merci ! en effet ça sera beaucoup plus lisible :oui:

sagemtek
sagemtek
Niveau 23
30 mars 2021 à 18:29:32

Le 30 mars 2021 à 18:16:12 Zsetea a écrit :

Le 30 mars 2021 à 17:55:54 sagemtek a écrit :

Le 30 mars 2021 à 17:49:06 Zsetea a écrit :
utilise des const à la place des let quand t'as pas besoin de muter une variable

J'ai souvent tendance à mettre des let ou var à chaque fois, mauvaise habitude de débutant. Je vais faire plus attention et mettre des const, par contre j'aurais voulu savoir pourquoi il ne faut pas utiliser forEach ? Je trouve ça plus ergonomique qu'une boucle for :(

Le 30 mars 2021 à 16:57:27 Pathos-II a écrit :
remplace les vars par let et const.
Quand tu crées un objet en JS, si le nom de l'attribut que tu as choisi est le même que le nom de la variable que tu lui passes en valeur, alors tu peux simplement mettre directement la variable.
ex :


let x = 1
let myObj = {
   x
}

au lieu de :


let xx = 1
let myObj = {
   x: xx
}

Je savais pas merci ! en effet ça sera beaucoup plus lisible :oui:

Parce que c'est plus lent tout simplement, la manière la plus propre d'itérer sur des collections c'est d'utiliser for of: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Statements/for...of

Merci de l'info :oui:
Il serait important d'éditer tout ça je pense vu que optimisation va de pair avec rapidité d'exécution.

wouh_pinaise_
wouh_pinaise_
Niveau 6
30 mars 2021 à 18:59:23

Non c'est complètement débile, tu perds en lisibilité pour aucun gain, et à la limite si ça te fait vraiment chier tu fais juste

if (tile2)
à la limite.

La conversion en booléen n'est effectivement pas nécessaire dans ce cas précis : if(tile2) est donc suffisant.

Par contre l'auteur je ne pense pas que tu sois obligé de remplacer tes foreach par des for si tu préfères l'écrire de cette manière.
Avant le foreach était effectivement plus lent, mais ça semble désormais dépendre du navigateur et de la version.

Ex de discussion sur le sujet (voir vidéo et discussion associées) : https://stackoverflow.com/questions/50844095/should-one-use-for-of-or-foreach-when-iterating-through-an-array

Pathos-II
Pathos-II
Niveau 22
30 mars 2021 à 21:54:22

Moi je suis pas vraiment d'accord le forEach est beaucoup plus clean car on comprend sans réfléchir qu'on itère sur un Array,
ça permet d'écrire moins de ligne et même une approche plus fonctionnelle avec le currying en faisant par exemple :

myArray.forEach(myFunc)

où myFunc sera appelée avec chaque élément du tableau. C'est beaucoup plus concis qu'avec un for of dans ce cas.
Il faut toujours prôner la lisibilité et la maintenabilité du code à la performance, sauf si on est vraiment dans un projet où la perf est vraiment quelque chose de recherchée.
Un for of je trouve que ça pollue la lisibilité de ta fonction car ça occupe le même scope que les instructions dans ta fonction alors qu'il est uniquement utilisé pour quelque chose qui peut utiliser son propre scope pour être traité. À l'inverse avec un forEach on voit tout de suite que la suite concernera uniquement l'Array sur lequel il est appelé.

De même, je préfère rester du côté fonctionnel (déclaratif vs impératif) et faire un map/filter pour manipuler mes tableaux plutôt que de faire des push, pop ou de créer des copies dans des boucles for (et ce même si cela est plus coûteux, ja garantie au moins l'idempotence dans un monde ou les lifecycles/comportement async ne sont pas toujours compris et peuvent jouer des tours aux devs moins expérimentés). Idem, je préfère recréer des copies avec le spread operator plutôt que d'altérer directement mes objets : cela permet d'avoir beaucoup de constantes ayant un nom expressif afin de comprendre ce que fait le code et de les utiliser en shorthand également (tout comme avec l'object destructuring).

Message édité le 30 mars 2021 à 21:56:59 par Pathos-II
Pathos-II
Pathos-II
Niveau 22
31 mars 2021 à 00:11:57

Le 30 mars 2021 à 23:54:53 Pathos-II a écrit :

Le 30 mars 2021 à 23:47:49 Pathos-II a écrit :

Le 30 mars 2021 à 23:05:33 Zsetea a écrit :

Le 30 mars 2021 à 21:54:22 Pathos-II a écrit :
Moi je suis pas vraiment d'accord le forEach est beaucoup plus clean car on comprend sans réfléchir qu'on itère sur un Array,
ça permet d'écrire moins de ligne et même une approche plus fonctionnelle avec le currying en faisant par exemple :

myArray.forEach(myFunc)

où myFunc sera appelée avec chaque élément du tableau. C'est beaucoup plus concis qu'avec un for of dans ce cas.
Il faut toujours prôner la lisibilité et la maintenabilité du code à la performance, sauf si on est vraiment dans un projet où la perf est vraiment quelque chose de recherchée.
Un for of je trouve que ça pollue la lisibilité de ta fonction car ça occupe le même scope que les instructions dans ta fonction alors qu'il est ua​imement utilisé pour quelque chose qui peut utiliser son propre scope pour être traité. À l'inverse avec un forEach on voit tout de suite que la suite concernera ua​imement l'Array sur lequel il est appelé.

De même, je préfère rester du côté fonctionnel (déclaratif vs impératif) et faire un map/filter pour manipuler mes tableaux plutôt que de faire des push, pop ou de créer des copies dans des boucles for (et ce même si cela est plus coûteux, ja garantie au moins l'idempotence dans un monde ou les lifecycles/comportement async ne sont pas toujours compris et peuvent jouer des tours aux devs moins expérimentés). Idem, je préfère recréer des copies avec le spread operator plutôt que d'altérer directement mes objets : cela permet d'avoir beaucoup de constantes ayant un nom expressif afin de comprendre ce que fait le code et de les utiliser en shorthand également (tout comme avec l'object destructuring).

Au vu de ce que t'écris j'ai pas l'impression que tu comprennes ce que c'est le currying parce que c'est hyper casse couille à faire en js, (tu peux go .bind mais c'est vraiment chiant et en pratique c'est chiant à lire)

En général quand tu fais un for of tu mutate pas l'array et au contraire je trouve que c'est beaucoup plus lisible d'écrire quelque chose comme


for (const a of as) {
  for (const b of bs) {
    f(a, b)
  }
}

plutôt qu'un


as.forEach(a => bs.forEach(f.bind(null, a)))

A moins d'avoir un langage entièrement fonctionnel comme haskell, le côté fonctionnel n'est intéressant que localement, c'est à dire que lorsque que tu peux faire un truc en une ligne élégamment par exemple, se baser ua​imement sur des .map dans un langage où tu ne peux pas composer facilement les fonctions ça donne du code vraiment illisible.

Ensuite "recréer des copites avec le spread operator" c'est vraiment la pire des choses à faire, autant au niveau performance qu'au niveau de la syntaxe, c'est totalement cryptique comme syntaxe.

Si tu veux faire ça tu utilises Object.assign({}, src, { a: 'b' }) si par exemple tu veux patch la propriété "a" sans modifier l'objet initial, mais encore une fois faire ça à la place de simplement faire src.a = 'b' ça n'a un intérêt que si l'objet src est partagé sinon ça ajoute juste de la complexité pour aucun gain.

Ça n'a vraiment aucun sens de se rajouter une barrière de ce genre dans un langage où l'immutabilité des objets n'est pas enforcé, ton code sera moins lisible, plus long à écrire et plus lent à l'execution.

Si tu veux écrire du fonctionnel, soit tu go elm soit tu go purescript, mais tu fais pas du pseudo fonctionnel immonde en javascript :(

Pardon je me suis trompé de terme je faisais référence au point-free
Après créer ses propres fonctions currifiés oui c'est un enfer, j'utilisais plutôt la lib Ramda pour faire ça :ok:
Mais je trouve le principe des HOF super bon enfait

Et sinon pour tes autres remarques je suis assez surpris car ces habitudes viennent surtout des guidelines Google et AirBnB que je trouvais + de leurs règles de Lint :hap:

ex :
https://github.com/airbnb/javascript#objects--rest-spread (copies avec le spread)
https://github.com/airbnbbnb/javascript#iterators--nope (éviter les blocks d'itérateurs)

Message édité le 31 mars 2021 à 00:12:30 par Pathos-II
Sous forums
  • Aide à l'achat Mac
  • Macintosh
  • Création de Jeux
  • Programmation
  • Création de sites web
  • Linux
  • Internet
  • Steam Deck
  • Hardware
La vidéo du moment