6 questions d’entretien d’embauche sur Spring

Le framework Spring a vu le jour en 2002, et il est depuis ce jour l’un des frameworks les plus populaires et aboutis. Pour peu qu’un développeur possède de bonnes connaissances en langage Java, les possibilités offertes par Spring sont infinies. C’est pour cette raison que les entreprises cherchent aujourd’hui à recruter des développeurs capables d’utiliser Spring, et que vous lisez cet article aujourd’hui.

Pour un recruteur, le meilleur moyen d’évaluer les compétences techniques de candidats pour un poste de développeur Spring est d’avoir recours à des tests de programmation. Recevoir les candidats les plus performants en entretien reste bien évidemment indispensable, mais il est important de faire une pré-sélection pour n’accorder du temps qu’aux candidats qui disposent des pré-requis techniques dans la technologie visée.

Voici une liste de 10 questions fondamentales permettant de couvrir un large éventail de sujets sur le framework Spring, allant des principes fondamentaux à certains sujets plus avancés.

N'oubliez pas que l'une des meilleures façons d'évaluer les compétences du candidat pour votre projet est de procéder à une évaluation pratique.

Citez quelques avantages du framework Spring

Avant que Spring ne prenne de l’importance, JEE était le choix évident pour développer une application. Mais ce dernier présentait de nombreuses limitations. Le code n’était pas assez modulaire, et plus l’application devenait importante, plus il devenait difficile d’identifier ses composants séparément. De plus, c’était un framework très lourd, qui avait tendance a dégrader les performances.

Spring a réussi a se défaires de tous les écueils du framework J2EE en un claquement de doigt. Spring est uniquement composé de « plain old Java objects » (c’est-à-dire de bons vieux objets Java, bien plus faciles à utiliser).

Enfin, le framework Spring peut-être utilisé pour le développement d’applications à interface graphique, d’applications web, d’applets, etc.

Bonnes réponses :

  • Cite l’avantage majeur Spring, à savoir la création d’une application composée de « plain old Java objects »
  • Explique les désavantages des méthodes utilisées auparavant

Réponses alarmantes :

  • Ne connaît pas les avantages du framework
  • Ne sait pas ce qu'est une application d'entreprise
  • N’a qu’une idée très basique des composants de Spring

Que pouvez-vous dire à propos de l’acronyme S.O.L.I.D, bien souvent utilisé en programmation orienté objet ?

Michael Feathers est connu pour avoir popularisé l’acronyme S.O.L.I.D, bien que Robert Martin soit l’inventeur de cette ligne directrice créée pour désigner les 5 principes de la programmation orientée objet. S.O.L.I.D signifie :

« Single responsibility principle » (Responsabilité unique)

« Open/Closed principle » (Ouvert/Fermé)

« Liskov substitution principle » (Substitution de Liskov)

« Interface segregation principle » (Ségrégation des interfaces)

« Dependency inversion principle » (Inversion des dépendances)

Le principe de la responsabilité unique stipule qu'aucune classe ne doit changer pour plus d'une raison et que chaque classe doit avoir une seule et unique responsabilité. Cela signifie que, même si vous pouvez mettre beaucoup de choses dans vos classes, vous ne devriez pas le faire. Les grandes classes doivent être divisées en petites classes et le concept d'une seule classe pour tout faire doit être évité à tout prix.

Le principe ouvert/fermé prévoit que toute classe doit être ouverte à l’extension mais fermée à la modification. Il faut uniquement créer des getters et des setters là où ils sont nécessaires, et garder privées les variables.

Selon la substitution de Liskov, les objets d’un programme doivent être remplaçables par leurs sous-types, sans entraîner une erreur.

La ségrégation des interfaces préconise qu’aucun client ne doit dépendre de méthodes qu’il n’utilise pas.

L’inversion des dépendances (à ne pas confondre avec l’injection des dépendances) prévoit que les modules de haut niveau ne doivent pas dépendre des modules de bas niveau, et que les abstractions ne doivent pas dépendre des détails (mais que les détails doivent dépendre des abstractions).

Bonnes réponses :

  • Avoir une idée claire de ces principes, étayer avec des exemples
  • Donnez des exemples de chaque principe, le cas échéant
  • Avoir une bonne compréhension de l'OOP

Réponses alarmantes :

  • Jamais entendu parler des principes du S.O.L.I.D
  • On ne peut pas donner d'exemples pour chacun des principes

Décrire les composantes du Spring Framework

Le framework Spring est composé d'une vingtaine de modules. Ces modules peuvent être regroupés sous les rubriques suivantes : conteneur de base, conteneur d'accès aux données/intégration, web, AOP, instrumentation et test. Le conteneur central est constitué des modules core, beans, de contexte et de langage d'expression. Les deux caractéristiques fondamentales du Spring Framework, à savoir l'injection de dépendance et l'inversion de contrôle, sont fournies par le module de base et beans.

La couche d'accès/intégration des données est une autre couche importante qui fournit les modules JDBC, ORM, OXM, JMS et Transaction. Le module JDBC évite au développeur de devoir coder la base de données en fonction du fournisseur. Le module ORM ou Object Relational Mapping permet de mapper des objets à des entités de base de données par le biais de JPA, JDO, Hibernate ou iBatis. Tous ces modules peuvent être utilisés et combinés entre eux. Le conteneur Web contient l'un des modules les plus importants, le module Web-Servlet, qui contient l'implémentation MVC de Spring pour les applications web. Le conteneur de test vous permet de tester les composants de Spring via JUnit ou TestNG.

Bonnes réponses :

  • Doit connaître le core, beans, JDBC, ORM, web modules.
  • Expliquez chacun des modules.

Réponses alarmantes :

  • Ne fait pas de distinction entre les différents modules
  • Ne comprend pas les modules à l'intérieur des conteneurs

Qu’est-ce qu’un conteneur IoC permet de faire sur Spring ?

Le conteneur d'inversion de contrôle de Spring est au cœur du framework de Spring. L'inversion de contrôle est une pratique générale du génie logiciel qui permet de transférer le contrôle sur des parties d'un programme ou des objets à un cadre/conteneur. L'inversion de contrôle permet au framework ou au conteneur de prendre le contrôle du programme et d'effectuer des appels à notre code.

Dans le cas de Spring, le conteneur IoC est implémenté au niveau de l’ApplicationContext Interface. Il prend tout en charge : initialisation, configuration et assemblage des beans tout au long de leur cycle de vie.

La configuration de l’IoC peut se faire par le biais de fichiers de configuration XML, d’annotations Java ou directement dans le code source Java.

Bonnes réponses :

  • L'inversion du contrôle comme principe général du génie logiciel
  • Comment Spring implémente l'IoC par l'injection de dépendance

Réponses alarmantes :

  • Je ne sais pas ce qu'est le IoC
  • Manque de compréhension entre l'IoC et l'injection de dépendance

Qu'entendez-vous par "injection de dépendance" ?

L'injection de dépendance est une technique de programmation par laquelle nous mettons en œuvre l'inversion de contrôle. Ici, le contrôle qui est inversé est le réglage des dépendances d'un objet. Il existe principalement trois façons de procéder à l'injection de dépendances. Il s'agit de l'injection de dépendance basée sur le constructeur, de l'injection de dépendance basée sur le régleur et de l'injection de dépendance basée sur le champ, également connue sous le nom d'autowiring.

Dans le constructeur DI, le conteneur IoC invoquera le constructeur avec les dépendances que nous voulons définir. Les informations de configuration pour cela peuvent être fournies soit par un fichier de configuration XML, soit par une classe de configuration Java.

L'injection de dépendance basée sur le setter est très similaire à l'injection basée sur le constructeur. La seule différence est qu'au lieu d'utiliser un constructeur, nous utilisons des setters et la configuration de ceux-ci peut être présente dans un fichier XML. Une autre façon de procéder consiste à utiliser l'annotation @Autowired qui peut être placée au-dessus des champs, des constructeurs, des setters et des propriétés.

Bonnes réponses :

  • Les différentes méthodes d'injection de la dépendance
  • En quoi les trois méthodes diffèrent l'une de l'autre
  • Donnez des exemples pour chacune des méthodes

Réponses alarmantes :

  • Ne connaît pas les trois méthodes d'injection de la dépendance
  • Ne peut pas donner d'exemples pour l'injection de dépendance du constructeur, du setter et autowired

Quelles sont les différences entre l’inversion de contrôle et une implémentation de classes POJO (plain old Java objects) ?

Imaginez que vous avez une interface, et une classe qui implémente cette interface. Cette classe aurait également des méthodes qui écrasent les implémentations de l’interface. Pour exécuter une fonction en particulier, il faudra créer un objet de cette classe, puis exécuter la fonction depuis l’instance de cet objet. Voilà le scénario classique en utilisant des classes POJO.

Que se passe-t-il si nous faisons exactement la même chose en utilisant le conteneur Spring IoC ? Ici, la création d'un objet est déléguée à une entité externe (Spring Framework). Sur la base des informations de configuration fournies dans le contexte de l'application, un objet nous est fourni par le conteneur IoC et nous pouvons appeler directement les méthodes qu'il contient.

Bonnes réponses :

  • Explique que la meilleure approche serait de poursuivre l’implémentation
  • Connaître le contexte de la demande

Réponses alarmantes :

  • Ne sait pas différencier les deux implémentations
  • Impossible d'expliquer ce que fait le conteneur Spring IoC

Pourquoi la configuration basée sur les annotations est-elle préférée à la configuration XML ?

Depuis la version 2.5 de Spring, l’injection des dépendances peut être réalisable en utilisant les annotations. Cela constitue une avancée majeure car un grand nombre de personnes détestaient l’ancienne norme, à savoir la configuration par le biais de fichiers XML. Grâce à la configuration basée sur les annotations, les dépendances peuvent être injectées directement dans la classe du composant en annotant une classe, un champ ou une méthode pertinente.

L'annotation @Configuration est utilisée pour spécifier que la classe peut être utilisée par le conteneur Spring IoC pour les définitions de bean. L'annotation suivante que nous utiliserons est le @Bean qui retournera l'objet d'un type particulier qui doit être enregistré avec le contexte de l'application.

Bonnes réponses :

  • Différences entre les deux méthodes de configuration
  • Décrire et expliquer les différentes annotations utilisées pour la configuration

Réponses alarmantes :

  • Ne connaît pas les différentes annotations de configuration

Qu'est-ce que la programmation réactive ?

La programmation réactive est un paradigme de programmation asynchrone qui se concentre sur les flux de données. Elle est essentiellement utilisée pour construire des systèmes qui sont résistants à une charge élevée. Il existe cinq caractéristiques principales de la programmation réactive. Elles sont :

- Flux de données - Les flux de données sont simplement des quantités continues de données. Cela peut être n'importe quoi, des interactions avec les utilisateurs, des appels de service RESTful, des transactions boursières, des listes de données provenant d'une base de données, etc.

- Asynchrone - Les événements relatifs aux flux de données sont saisis de manière asynchrone. Il peut y avoir différentes fonctions qui sont définies pour s'exécuter lorsqu'un événement ou une erreur est émis, ou lorsque le flux de données complet est émis.

- Non-blocage - C'est un concept très important lorsqu'il s'agit de programmation réactive. Il existe deux modes de fonctionnement, le blocage et le non-blocage. Dans le mode de fonctionnement bloquant, le code attend des données avant de procéder (lecture à partir d'un disque, d'un réseau, etc.), tandis que dans le mode de fonctionnement non bloquant, les données en main seront traitées et demanderont à être notifiées lorsque d'autres données seront disponibles.

- Contre-pression - Imaginez une situation dans laquelle une API a du mal à traiter les demandes. Dans un tel scénario, elle ne devrait pas échouer à fonctionner ou abandonner l'un des messages de manière aléatoire. Elle devrait plutôt informer les sources en amont de sa situation et contrôler le trafic qui lui parvient. C'est ce que l'on appelle la contre-pression et c'est un autre aspect important de la programmation réactive.

- Les défaillances en tant que messages - Comme la programmation réactive se fait par le biais de flux de données, nous ne lançons pas d'exceptions car cela briserait le traitement du flux. Au lieu de cela, nous le traitons en utilisant des messages par le biais de fonctions de traitement.

Bonnes réponses :

  • Les 5 caractéristiques de la programmation réactive
  • La contre-pression et le non-blocage doivent être expliqués clairement

Réponses alarmantes :

  • Ne peut pas donner d'exemples de flux de données asynchrones
  • Ne peut pas expliquer le non-blocage et la contre-pression

Comment le framework Spring facilite-t-il l'accès aux données ?

1
@Entity public class Author{ @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String publisher; @ManyToMany(mappedBy = “authors”) private Set books = new HashSet<>(); //Assume we have the relevant constructor, getters and setters } @Entity public class Book{ @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String title; private String isbn; @ManyToMany @JoinTable(name = “author_book”, joinColumns = @JoinColumn(name = “book_id”), inverseJoinColumns = @JoinColumn(name = “author_id”)) private Set authors = new HashSet<>(); //Assume we have the relevant constructor, getters and setters }

Prenez note des annotations ci-dessus. L'annotation @Entity définit la classe Auteur et la classe Livre comme une entité. L'annotation @Id représente le champ qui est utilisé pour identifier de manière unique chaque ligne de la base de données. L'annotation @GeneratedValue représente la manière dont la clé unique est générée. @ManyToMany définit une relation "many to many" et l'annotation @JoinColumn est utilisée pour joindre les colonnes sur la base de l'identifiant fourni.

En exécutant cet exemple, Spring crée automatiquement la table Author, la table Book et la table jointe Author_Book dans la base de données en mémoire sans notre intervention.

Pour accéder aux données également, il existe en Spring un moyen très simple d'utiliser les dépôts de l'APP. Pour cela, nous pouvons créer une interface AuthorRepository qui étend le CrudRepository. Le CrudRepository dispose de méthodes intégrées comme save, findById, existsById, findAll, deleteById, delete, etc.

Bonnes réponses :

  • Expliquer les annotations utilisées
  • Utilisation des dépôts et des méthodes disponibles

Réponses alarmantes :

  • Impossible d'expliquer clairement par un exemple
  • Manque de connaissance des annotations

Expliquer l'annotation @RequestMapping et comment elle est utilisée dans les applications web

@RequestMapping est l'une des principales annotations de Spring MVC. Il met en correspondance les méthodes des requêtes web avec les méthodes présentes à l'intérieur du contrôleur.

1
@RequestMapping(value = “/all”, method = RequestMethod.GET) @ResponseBody public String listAll(){ return “Inside controller method”; }

Dans l'exemple ci-dessus, la valeur représente l'URI et la méthode représente le type de demande attendu. L'annotation @ResposneBody est utilisée pour envoyer la réponse String pour cette requête web.

Bonnes réponses :

  • Connaissance de l'annotation RequestMapping
  • Types de méthodes possibles en dehors de l'EEG

Réponses alarmantes :

  • N'ont jamais entendu parler de @RequestMapping
  • Impossible de donner un aperçu du flux entre la demande web et le contrôleur

Conclusion

Nous espérons que ces quelques questions pourront vous aider à mieux comprendre comment interroger un développeur Spring lors d’un entretien d’embauche. Toutefois, tester les compétences réelles d’un candidat est beaucoup plus efficace en utilisant une solution de tests techniques de programmation. Ceux-ci permettent d’évaluer tous vos candidats de manière équitable, et de comparer leurs résultats très simplement grâce à des rapports de performance personnalisés.