La différence entre une API NodeJS / Java

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J’aimerai confirmer une hypothèse que je me suis faite au gré de mes expériences professionnelles.

J’ai évolué dans l’écosystème NodeJS pour diverses sociétés, mais généralement, c’était pour de l’API back et aussi souvent du scraping (notamment dans le secteur bancaire / automatisations de leads).

Ce que j’ai souvent vécu avec JS (et même TS), c’est globalement :

  • Une grande flexibilité dans le développement, permettant de s’adapter rapidement aux besoins changeants des projets
  • Une communauté très active et une quantité impressionnante de packages disponibles, ce qui facilite l’implémentation de nouvelles fonctionnalités

mais également :

  • Une certaine difficulté à maintenir la qualité du code sur le long terme, surtout dans des projets de grande envergure, en raison de la flexibilité même du langage
  • Des défis relatifs au typage dynamique, qui, malgré l’ajout de TypeScript, peuvent parfois rendre le débogage et la refonte plus complexes

Quant à Java, c’était plutôt des API pour des clients grands comptes (type Leroy Merlin et compagnie), et j’avoue que mon verdict est quelque peu différent.

  • La robustesse du typage statique de Java et le framework Spring Boot offrent une structure solide pour le développement, la maintenance et l’évolutivité des applications.
  • Une meilleure gestion des dépendances et une architecture bien définie qui facilitent la mise en place de bonnes pratiques de codage et la maintenabilité du code.

mais également :

  • Un temps de démarrage des projets potentiellement plus long en raison de la configuration initiale plus lourde et de la courbe d’apprentissage plus raide de Spring Boot comparée à certains outils NodeJS
  • Une flexibilité moindre pour les modifications rapides et les itérations courtes, ce qui peut être perçu comme un frein dans des environnements très dynamiques

Je suis curieux de savoir si d’autres partagent cette perception ou si mes expériences ont été atypiques. Quels sont vos avis sur la facilité de modélisation et la qualité du développement entre Java Spring Boot et NodeJS, surtout dans le contexte de projets à grande échelle ou critiques ?

Je m’étais inscrit dans le but de poser une question sur un autre sujet, mais je vois que je peux te donner mon expérience et mon ressenti sur tes premiers points.

Je n’ai pas le recul nécessaire pour rebondir sur le sujet de Java Spring, mais j’en ai tout de même un aperçu.


  • Une certaine difficulté à maintenir la qualité du code sur le long terme, surtout dans des projets de grande envergure, en raison de la flexibilité même du langage

En prenant Express comme exemple, tu as tout à fait raison. Cependant, si tu regardes Nest.js, tu constateras que c’est un excellent framework adapté aux gros projets. Cependant, en utilisant un framework complet de ce type, tu reviens à ton argument initial : un temps de démarrage des projets potentiellement plus long, ce qui est généralement vrai pour tous les gros frameworks de type Symfony, Java Spring et Django sur certains aspects.

  • Des défis relatifs au typage dynamique, qui, malgré l’ajout de TypeScript, peuvent parfois rendre le débogage et la refonte plus complexes

Je pense que c’est une question d’habitude et de goût. Cela fait longtemps que je n’ai pas rencontré de problème de ce type sur mes programmes (Pourtant, sur la plupart de mes projets en solo, j’utilise JavaScript, mais je triche un peu car je sais à l’avance le type de programme qui nécessite TypeScript par rapport à JavaScript, notamment lorsque j’implémente des structures de données telles qu’un arbre binaire ou des algorithmes d’optimisation, avec des classes qui s’héritent entre elles et qui n’ont pas toutes les mêmes propriétés getter/setter. Cependant, en général, les applications se limitent à des classes telles que Product, Customer, Invoice. Ainsi, tu es capable de différencier les types par toi-même, sans forcément passer par TypeScript).

Le fait de choisir des noms de variables clairs et qui ne se chevauchent pas aide beaucoup. De plus, si le nom de variable est ambiguë, tu peux préfixer tes variable avec des mots clefs sur le type ou l’état de la variable en question.

Par ailleurs, à un moment donné (il y a longtemps), le débogueur Eclipse était en avance par rapport à ce qui pouvait être fait en JS. Mais maintenant, avec VS Code ou JetBrains, tu as de très bons outils pour le débogage, que ce soit en TypeScript ou en JavaScript.


EDIT : En relisant, je remarque que mon discours penche d’un côté pro Javascript, ce n’est pas vraiment le message que je souhaite faire passer. En travaillant en équipe, je suis convaincu que l’utilisation d’un langage avec typage représente un compromis plus avantageux. Dans le contexte de JavaScript, la diversité des approches pour implémenter une classe peut rapidement engendrer de la confusion où chacun fait à sa sauce.

+0 -0

De mon point de vue de développeur principalement Java mais qui fait aussi du JS, mon avis personnel est le suivant.

Pour commencer, le principal impact sur la qualité de l’implémentation d’une API, ça n’est pas le langage utilisé, mais les développeurs. Tu peux avoir une API très propre et implémentée proprement avec un langage bancal si l’équipe est rigoureuse ; tu peux avoir une API dégueulasse implémentée n’importe comment avec un langage ultra-rigide si l’équipe est constituée de clowns.

Cela dit, à développeurs de qualité identique, ton analyse est assez exacte @Flake. Des projets que j’ai croisé, JavaScript (ou même TypeScript) va être plus souple et permettre d’être plus « efficace » et réactif pour démarrer un projet, mais être plus difficile à maintenir sur le long terme, plus difficile sur les projets complexes et sensible aux manques de rigueur. Un projet Java ou Kotlin (ou n’importe quel langage moderne avec du typage fort et statique, et de bons frameworks webs) va être plus rigide et verbeux, mais va laisser passer beaucoup moins d’approximations et de bidouilles à la compilation, et sera naturellement plus résistant au manque de rigueur. D’une manière générale tu vas y retrouver plus facilement tes petits lors de la maintenance parce qu’il y a aura moins de comportements à deviner, du fait du typage.

La principale limite d’utiliser un tel langage pour consommer une API quelconque, c’est quand l’API est mal fichue et renvoie des objets de structure différente selon le contexte ; ou quand elle renvoie des objets beaucoup trop gros et complexes. L’avantage d’utiliser un tel langage pour fournir une telle API, c’est qu’on va naturellement avoir à éviter ce genre d’écueil…

Le monde Java a fait de gros progrès en terme de verbosité, d’ailleurs. Par exemple, pour utiliser une API protégée par OIDC depuis une application Quarkus en Java, j’ai juste besoin de faire ceci  (je vous épargne les imports) :

@RegisterRestClient(configKey = "myuplink")
@OidcClientFilter
@Path("/")
public interface DevicesResource {

    @GET
    @Produces("application/json")
    @Path("v3/devices/{deviceId}/points")
    List<Point> getPoints(@PathParam("deviceId") String deviceId, @HeaderParam("Accept-Language") String locale);
}

(Il n’y a pas besoin de coder une implémentation de cette interface, c’est géré tout seul par le moteur).

Bien sûr, il faut définir le type de retour, et ça se fait comme ça – avec un type très verbeux :

public record Point(
        String category,
        String parameterId,
        String parameterName,
        String parameterUnit,
        boolean writable,
        OffsetDateTime timestamp,
        BigDecimal value,
        String strVal,
        List<String> smartHomeCategories,
        BigDecimal minValue,
        BigDecimal maxValue,
        BigDecimal stepValue,
        List<EnumValue> enumValues,
        String scaledValue,
        String zoneId) {}
        
public record EnumValue(String value, String text, String icon) {}

(Source : https://github.com/SpaceFox/myuplink-data-retriever/tree/master/src/main/java/fr/spacefox/myuplink/client)

À l’utilisation, il suffit juste d’injecter la DevicesResource et d’utiliser la méthode getPoints(), si OIDC est correctement configuré (c’est littéralement trois clés : l’URL, le nom du client et le secret), ça fonctionne.

Cependant, en général, les applications se limitent à des classes telles que Product, Customer, Invoice. Ainsi, tu es capable de différencier les types par toi-même, sans forcément passer par TypeScript).

Ça doit dépendre des projets, parce que mon expérience, c’est plutôt que les API peuvent rapidement devenir complexes, avec des objets qui se ressemblent sans être identiques (avec la question classique : quels champs sont disponibles dans quel objet ?). Même dans un contexte e-commerce.

PS : avis très personnel : dans tous les cas, je ne comprends pas qu’un projet qui a le choix de la technologie (donc pas du front web) et qui ait vocation à être développé par une « grosse » équipe et/ou être maintenu sur plus de 6 mois utilise autre chose qu’un langage avec du typage statique fort, tant le gain en robustesse, en maintenabilité et en découverte de bugs potentiels avant l’exécution est important.

Salut, je partage plutôt ce que tu dis.

Sur les projets Node, qu’ils soient en JS ou TS, je te rejoins sur la maintenabilité du code. Mais cela ne me semble pas être du au langage à lui même.
Ce que j’ai constaté c’est que comme le langage est permissif les développeurs appliquent leurs style de code personnel quand les règles ne sont pas précisé ou flou. Cet effet est aussi amplifié par le turn-over qu’il peut y avoir sur les projets dans lesquels parfois les règles peuvent changer en fonction de la préférence majoritaire des dev de l’équipe.

Je te rejoins aussi sur ce que tu critique sur l’environnement Java.
Des projets plus long à démarrer. Pour moi ça me semble normal car les outils comme spring boot car il peuvent tout faire (mais je reviendrai sur ce point plus tard).
De plus comme tous les gros outils, spring boot est un outils pour résoudre un type de problème. Quand on cherche à aller dans les cas limites (parce que le besoins du projet à changé) parfois l’outil initialement choisi n’est plus adapté pour résoudre la problématique et semble donc peu flexible.


Quelque chose que je voudrai souligner est l’approche pour résoudre un problème entre d’un coté Java et de l’autre Node.
Ici on peut mettre d’un coté les gros outils comme Java spring boot, ou encore Python Django en opposition à des choses comme Node, Go ou encore Python Flask (voir bottle).

Je pense que l’approche pour résoudre des problématiques entre ces deux groupes est totalement différents.

  1. Venir avec des plans
  2. Faire les plans sur place

Du coté de spring boot pour moi on viens avec tous les plans dessiné pour construire notre maison. Parce que dans 90% du temps on veut construire une maison alors autant utiliser ce qu’on a déjà quitte à apporter des petites modifications pour obtenir exactement ce que l’on à besoins.
Ici la dérive est de devoir faire trop de petite modification et au final ne pas avoir pris les bon plans initialement.
Cela à cependant l’avantage d’initialiser un projet très rapidement et de tout de suite voir notre maison se construire

De l’autre coté l’approche me semble différents, on va se reposer les questions de ce que l’on souhaite et comment.
Cette manière d’aborder notre construction nous permet de dessiner nos plans de maison (ou de tout autre bâtiment) pour avoir exactement ce que l’on souhaite et de se rendre compte dès l’étape 0 de ce que l’on a réellement besoins.
La dérive est que lorsque l’on fait plusieurs fois la même chose on va se poser encore les même question et avoir ENCORE les mêmes réponses. Cela peut donner aussi l’impression que le projet avance moins vite au début car il faut tout construire. Le gros avantage est d’avoir tout de suite ce qu’on a exactement besoins dans avoir l’apprentissage d’un plan que l’on ne connais pas forcément bien (par exemple pour faire du Django il faut apprendre Django qui est plus long à prendre en main que Flask de par la complexité de cet outils).

Je pense que ces deux approches ne sont que des outils pour apporter une solution.
Si l’on doit faire des API CURLD (Create, Update, Read, List, Delete) à la chaine, dans ce car un outils comme spring boot me semble être un bon investissement. On passe du temps à apprendre un outils qu’on va beaucoup utiliser.
Dans le cas où on ne sait pas exactement où on va, ce qu’on veut faire, comment on va le faire, dans quel sens, … utiliser des outils plus minimalistes, me semble plus facile. De ce fait on va passer moins de temps à l’instant T à apprendre à utiliser par exemple Flask pour se concentrer sur notre solution. (Quitte à en suite jeter Flask et utiliser un autre outils qui semblerai plus adapté) Le freins va devenir la conception de notre solution et non l’apprentissage de(s) outil(s) qui vont permettre la conception.

Je pense que c’est aussi une question d’approche de conception de solution et de préférence à chaqu’un.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte