Chapitre 1629 minIntermédiaire
POO à l'examen : méthode, exercices corrigés et aide-mémoire
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- traiter une question de code objet avec méthode ;
- lire un sujet écrit en Java ou en PHP ;
- traduire un diagramme de classes en code complet ;
- critiquer et corriger une classe ;
- retrouver vite la syntaxe objet de C#.
5 exercices corrigés
Ce dernier chapitre rassemble ce qu'il faut pour réussir les questions de programmation objet au BTS SIO SLAM : où elles tombent, une méthode pour traiter une question de code sur papier, les équivalences entre C#, Java et PHP pour lire un sujet écrit dans un autre langage, des exercices de synthèse corrigés du type E6 et E7, et un aide-mémoire de la syntaxe objet de C#.
Où la POO tombe au BTS SIO
| Épreuve | Ce qu'on te demande en POO |
|---|---|
| E6 SLAM, conception et développement d'applications (oral, bloc 2) | expliquer les classes de tes deux réalisations et faire évoluer ton propre code pendant l'heure de réalisation : ajouter une propriété, une règle de gestion, une classe fille, une méthode testée (déroulement de l'E6 SLAM) |
| E7 SLAM, cybersécurité des services informatiques (écrit, 4 h) | lire et compléter des classes métier dans le langage du sujet (souvent Java ou PHP), écrire une méthode de contrôle qui parcourt des collections, critiquer ou corriger un code (lire et écrire du code sur papier) |
| Travail en atelier et réalisations du portfolio | concevoir les classes d'une application à partir d'un besoin, avec un diagramme de classes (cours UML) |
Le référentiel du BTS SIO range la programmation objet dans les savoirs du bloc 2 de l'option SLAM : classes et objets, abstraction, interfaces, héritage, polymorphisme, annotations, patrons de conception et interfaces de programmation (traitées dans le cours API REST). Les autres notions ont chacune leur chapitre ici.
La méthode pour une question de code objet
- Lis le diagramme de classes ou les classes fournies avant l'énoncé de la question. Note pour chaque classe ses propriétés, ses méthodes et ses associations : c'est ta boîte à outils, et le correcteur attend que tu t'en serves.
- Repère le chemin entre les objets. « Le montant total des contrats d'un fournisseur » : fournisseur → collection de contrats → montant. Chaque flèche du chemin devient un accès (
unContrat.getMontant()) ou une boucle (foreach). - Écris la signature exacte demandée (nom, paramètres, type de retour), dans la classe demandée.
- Écris le corps : initialise le résultat, parcours, teste, cumule, renvoie. Utilise les méthodes documentées dans le sujet, même si tu en connais d'autres.
- Déroule ton code sur un exemple au brouillon, avec un cas limite : une collection vide, un élément qui ne satisfait pas la condition, le dernier élément.
Lire du Java quand on connaît C#
Java et C# se ressemblent au point qu'un sujet en Java se lit sans l'avoir appris. Les différences à connaître :
| Notion | C# | Java |
|---|---|---|
| Hériter | class Portable : Poste | class Portable extends Poste |
| Implémenter une interface | class Ticket : IExportableCsv | class Ticket implements ExportableCsv |
| Appeler le constructeur parent | : base(num, marque) après la signature | super(num, marque); en première ligne du corps |
| Appeler la méthode parente | base.Decrire() | super.decrire() |
| Redéfinir | virtual dans la mère, override dans la fille | tout est redéfinissable ; @Override (facultatif) au-dessus |
| Interdire l'héritage | sealed | final |
| Accesseurs | propriété Nom { get; set; } | méthodes getNom() et setNom(…) |
| Constante | const, readonly | final |
| Liste | List<Ticket>, .Add(), .Count, [i] | ArrayList<Ticket>, .add(), .size(), .get(i) |
| Parcourir | foreach (Ticket t in liste) | for (Ticket t : liste) |
| Comparer deux chaînes | a == b | a.equals(b) (jamais ==) |
| Conventions de nommage | méthodes en PascalCase | méthodes en camelCase |
| Exception d'argument | ArgumentException | IllegalArgumentException |
Lire du PHP objet
| Notion | PHP 8 |
|---|---|
| Classe, propriété typée | class Ticket { private string $titre; } |
| Constructeur | public function __construct(string $titre) { $this->titre = $titre; } |
| Promotion des paramètres du constructeur | public function __construct(private string $titre) {} |
| Accès à un membre | $this->titre, $ticket->getTitre() (la flèche remplace le point) |
| Membre statique | self::$compteur, Ticket::creer() |
| Héritage, parent | class Portable extends Poste, parent::__construct($num); |
| Interface, classe abstraite | implements, abstract class, abstract public function |
| Tableau d'objets | $lesTickets = [];, $lesTickets[] = $t;, count($lesTickets), foreach ($lesTickets as $t) |
Le cours PHP et MySQL montre la programmation objet en PHP, avec PDO.
Les erreurs qui coûtent des points
| Erreur | Correction |
|---|---|
Champ public, ou propriété avec un set public sur une donnée qui a des règles | private + propriété en lecture seule ou méthode métier qui valide |
Constructeur de la fille sans base(...) / super(...) | appeler le constructeur parent avec les données qu'il exige |
override sans virtual dans la mère (C#) | déclarer la méthode virtual ou abstract dans la mère |
new Materiel(...) sur une classe abstraite | instancier une classe concrète |
| Confondre surcharge (paramètres différents) et redéfinition (même signature, classe fille) | voir le tableau du chapitre 8 |
Association traduite en attribut int idEmploye | une référence vers l'objet : Employe leDemandeur |
Collection exposée en écriture (public List<…>) | liste privée, exposée en IReadOnlyList<…>, méthodes Ajouter… |
return false; dans un else à l'intérieur de la boucle | return false; après la boucle |
== entre deux chaînes en Java | equals() |
Equals redéfini sans GetHashCode | les deux ensemble |
Exercice de synthèse 1 : du diagramme de classes au code
Exercice 1 sur 5 Les prêts de portables Réussi À revoir
Le service informatique de Sorbier Logistique prête des portables aux salariés en déplacement. Le diagramme de classes, au format texte :
Salarie:- nom : string,- prenom : string.Portable:- numInventaire : string,- marque : string;+ EstDisponible() : bool,+ Preter(salarie : Salarie, debut : DateOnly, retourPrevu : DateOnly) : Pret.Pret:- dateDebut : DateOnly,- dateRetourPrevue : DateOnly,- dateRetourReelle : DateOnly [0..1],- etatRetour : string [0..1];+ EstEnCours() : bool,+ EnregistrerRetour(date : DateOnly, etat : string) : void,+ EstEnRetard(jour : DateOnly) : bool,+ JoursDeRetard(jour : DateOnly) : int.Portable 1 —— 0..* Pret(rôleslePortableetlesPrets),Pret 0..* —— 1 Salarie(rôleleSalarie, navigable du prêt vers le salarié).
Règles de gestion :
-
un prêt est en cours tant que le portable n'est pas rendu ;
-
un portable est disponible si aucun de ses prêts n'est en cours ;
Preterlève uneInvalidOperationExceptionsinon ; -
le retour prévu ne peut pas précéder le début du prêt ;
-
un prêt est en retard si, au jour donné, il est en cours et la date de retour prévue est dépassée ;
JoursDeRetardrenvoie 0 s'il n'est pas en retard ; -
on ne peut pas enregistrer deux fois le retour d'un prêt.
- Écris les classes
PortableetPret(Salarieest fournie). - Karim Morel emprunte le portable PC-0021 du 12 au 23 octobre 2026. Le 2 novembre 2026, que renvoient
EstDisponible(),EstEnRetard(jour)etJoursDeRetard(jour)?
Voir la réponseMasquer la réponse de l'exercice 1
class Portable
{
private readonly List<Pret> lesPrets = new List<Pret>();
public Portable(string numInventaire, string marque)
{
NumInventaire = numInventaire;
Marque = marque;
}
public string NumInventaire { get; }
public string Marque { get; }
public IReadOnlyList<Pret> LesPrets => lesPrets;
public bool EstDisponible()
{
foreach (Pret p in lesPrets)
{
if (p.EstEnCours())
{
return false;
}
}
return true;
}
public Pret Preter(Salarie salarie, DateOnly debut, DateOnly retourPrevu)
{
if (!EstDisponible())
{
throw new InvalidOperationException($"Le portable {NumInventaire} est déjà prêté.");
}
Pret p = new Pret(this, salarie, debut, retourPrevu);
lesPrets.Add(p);
return p;
}
}
class Pret
{
internal Pret(Portable portable, Salarie salarie, DateOnly debut, DateOnly retourPrevu)
{
if (retourPrevu < debut)
{
throw new ArgumentException("Le retour prévu précède le début du prêt.");
}
LePortable = portable;
LeSalarie = salarie;
DateDebut = debut;
DateRetourPrevue = retourPrevu;
}
public Portable LePortable { get; }
public Salarie LeSalarie { get; }
public DateOnly DateDebut { get; }
public DateOnly DateRetourPrevue { get; }
public DateOnly? DateRetourReelle { get; private set; }
public string? EtatRetour { get; private set; }
public bool EstEnCours() => DateRetourReelle is null;
public void EnregistrerRetour(DateOnly date, string etat)
{
if (!EstEnCours())
{
throw new InvalidOperationException("Ce prêt est déjà clos.");
}
if (date < DateDebut)
{
throw new ArgumentException("Le retour précède le début du prêt.");
}
DateRetourReelle = date;
EtatRetour = etat;
}
public bool EstEnRetard(DateOnly jour) => EstEnCours() && jour > DateRetourPrevue;
public int JoursDeRetard(DateOnly jour) =>
EstEnRetard(jour) ? jour.DayNumber - DateRetourPrevue.DayNumber : 0;
}
Le 2 novembre 2026 : EstDisponible() renvoie false (le prêt est en cours), EstEnRetard(jour) true, JoursDeRetard(jour) 10 (8 jours du 24 au 31 octobre, plus le 1er et le 2 novembre). DayNumber donne le numéro du jour depuis le 1er janvier de l'an 1 : la différence de deux DayNumber est un nombre de jours.
Ce qu'un correcteur regarde en priorité : les multiplicités [0..1] traduites en types nullables ; l'association 0..* en liste privée exposée en lecture seule ; Preter qui crée le prêt (le constructeur internal empêche de créer un prêt hors de Preter, donc hors de la liste) ; EstDisponible avec le return true après la boucle ; les dates de retour en private set, modifiées seulement par EnregistrerRetour.
Tu avais trouvé ?
Exercice de synthèse 2 : compléter une classe
Exercice 2 sur 5 Deux méthodes pour le ticket Réussi À revoir
La classe Ticket est fournie : elle a les propriétés Numero, Titre, DateOuverture (DateTime) et DateCloture (DateTime?, nulle tant que le ticket n'est pas résolu), et une liste privée interventions d'objets Intervention (propriétés Technicien de type Employe, Date, DureeMin).
- Écris
TimeSpan? DelaiResolution(), qui renvoie la durée entre l'ouverture et la clôture, ounullsi le ticket n'est pas résolu. - Écris
Employe? TechnicienPrincipal(), qui renvoie le technicien qui a passé le plus de temps sur le ticket (nulls'il n'y a aucune intervention). - Le ticket 4, ouvert le 2 novembre 2026 à 9 h et résolu à 15 h 45, a reçu trois interventions : Chloé 40 min, Moussa 90 min, Chloé 30 min. Donne les résultats.
Voir la réponseMasquer la réponse de l'exercice 2
public TimeSpan? DelaiResolution() => DateCloture - DateOuverture;
public Employe? TechnicienPrincipal() =>
interventions.GroupBy(i => i.Technicien)
.OrderByDescending(g => g.Sum(i => i.DureeMin))
.Select(g => g.Key)
.FirstOrDefault();
Soustraire un DateTime d'un DateTime? nul donne null : la première méthode n'a pas besoin de if. Une version sans LINQ, plus proche de ce qu'on écrit en Java, cumule les durées dans un Dictionary<Employe, int>, puis cherche la plus grande valeur.
Résultats : DelaiResolution() vaut 06:45:00 (6 h 45, soit TotalHours = 6,75) ; TechnicienPrincipal() renvoie Moussa (90 minutes contre 40 + 30 = 70 pour Chloé). Le regroupement porte sur l'objet Employe : sans redéfinition d'Equals, deux objets différents pour la même personne compteraient comme deux techniciens (chapitre 11).
Tu avais trouvé ?
Exercice de synthèse 3 : critiquer une classe
Exercice 3 sur 5 La réservation de salle Réussi À revoir
Un stagiaire a écrit cette classe pour réserver les salles de réunion. Relève au moins cinq défauts d'encapsulation ou de conception, puis propose une version corrigée.
public class Reservation
{
public static List<Reservation> Toutes = new List<Reservation>();
public string Salle;
public DateTime Debut;
public DateTime Fin;
public List<string> Participants = new List<string>();
public int NbParticipants;
public Reservation(string salle, DateTime debut, DateTime fin)
{
Salle = salle; Debut = debut; Fin = fin;
Toutes.Add(this);
}
public void AjouterParticipant(string email)
{
Participants.Add(email);
NbParticipants++;
}
public bool Chevauche(Reservation autre) =>
Salle == autre.Salle && Debut < autre.Fin && autre.Debut < Fin;
}
Voir la réponseMasquer la réponse de l'exercice 3
Les défauts :
- Champs publics (
Salle,Debut,Fin) : on peut déplacer une réservation sans aucune vérification. - Aucune validation : une fin antérieure au début est acceptée.
- Liste exposée :
Participants.Add(...)depuis l'extérieur contourneAjouterParticipant. - Donnée dérivée stockée :
NbParticipantspeut diverger deParticipants.Count(et il est public en écriture). - Doublons et capacité : le même participant peut être ajouté deux fois, et rien ne limite le nombre de personnes.
- Liste statique globale
Toutes: la classe se range elle-même dans un registre global, ce qui mélange deux responsabilités, rend les tests dépendants les uns des autres et ne correspond à aucune persistance réelle. C'est le rôle d'un repository (chapitre 13).
public class Reservation
{
private readonly HashSet<string> participants = new(StringComparer.OrdinalIgnoreCase);
public Reservation(string salle, DateTime debut, DateTime fin, int capacite)
{
ArgumentException.ThrowIfNullOrWhiteSpace(salle);
if (fin <= debut)
{
throw new ArgumentException("La fin doit être postérieure au début.");
}
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(capacite);
Salle = salle;
Debut = debut;
Fin = fin;
Capacite = capacite;
}
public string Salle { get; }
public DateTime Debut { get; }
public DateTime Fin { get; }
public int Capacite { get; }
public IReadOnlyCollection<string> Participants => participants;
public int NbParticipants => participants.Count;
public void AjouterParticipant(string email)
{
if (participants.Count >= Capacite)
{
throw new InvalidOperationException($"La salle {Salle} est complète.");
}
participants.Add(email.Trim());
}
public bool Chevauche(Reservation autre) =>
Salle == autre.Salle && Debut < autre.Fin && autre.Debut < Fin;
}
Le HashSet avec un comparateur insensible à la casse élimine les doublons d'adresse. Chevauche était juste : deux créneaux se chevauchent si chacun commence avant la fin de l'autre ; une réservation de 9 h à 10 h 30 et une de 10 h 30 à 11 h ne se chevauchent pas.
Tu avais trouvé ?
Exercice de synthèse 4 : un sujet en Java
Exercice 4 sur 5 Les abonnements logiciels Réussi À revoir
Le dossier documentaire d'un sujet fournit ces classes Java.
public abstract class Abonnement {
protected String libelle;
protected double prixMensuel;
public Abonnement(String libelle, double prixMensuel) {
this.libelle = libelle;
this.prixMensuel = prixMensuel;
}
public abstract double coutAnnuel();
@Override
public String toString() {
return this.libelle + " : " + this.coutAnnuel() + " €";
}
}
public class AbonnementStandard extends Abonnement {
public AbonnementStandard(String libelle, double prixMensuel) {
super(libelle, prixMensuel);
}
@Override
public double coutAnnuel() {
return this.prixMensuel * 12;
}
}
public class AbonnementEngagement extends Abonnement {
private int remisePourcent;
public AbonnementEngagement(String libelle, double prixMensuel, int remisePourcent) {
super(libelle, prixMensuel);
this.remisePourcent = remisePourcent;
}
@Override
public double coutAnnuel() {
return this.prixMensuel * 12 * (100 - this.remisePourcent) / 100;
}
}
- Pourquoi
Abonnementest-elle abstraite ? Que se passe-t-il si on écritnew Abonnement("Test", 10)? - Quel principe de la POO permet à
toString(), écrite dansAbonnement, d'afficher le bon coût ? - Donne l'affichage de
System.out.println(a)pour chacun de ces abonnements : messagerie standard à 12,50 € par mois ; sauvegarde en ligne avec engagement à 20 € par mois et 25 % de remise ; antivirus avec engagement à 4 € par mois sans remise. - Écris en Java la méthode statique
double coutTotal(ArrayList<Abonnement> lesAbonnements)qui renvoie le coût annuel total, et donne sa valeur pour les trois abonnements.
Voir la réponseMasquer la réponse de l'exercice 4
Abonnementdéclare une méthode abstraite,coutAnnuel(): un abonnement « en général » ne sait pas calculer son coût, seules les classes filles le savent. Une classe qui a une méthode abstraite doit être abstraite.new Abonnement("Test", 10)ne compile pas : on n'instancie pas une classe abstraite.- Le polymorphisme (liaison dynamique) :
this.coutAnnuel()exécute la version de la classe réelle de l'objet. En Java, toutes les méthodes sont redéfinissables par défaut, sans mot-clévirtual. -
12,5 × 12 = 150 ; 20 × 12 × 75 / 100 = 180 ; 4 × 12 × 100 / 100 = 48. Java affiche un
Messagerie : 150.0 € Sauvegarde en ligne : 180.0 € Antivirus : 48.0 €doubleavec un point et au moins une décimale :150.0. -
Valeur : 378.0 (150 + 180 + 48). La boucle ne teste pas le type de l'abonnement : chaque objet calcule son propre coût.
public static double coutTotal(ArrayList<Abonnement> lesAbonnements) { double total = 0; for (Abonnement unAbonnement : lesAbonnements) { total = total + unAbonnement.coutAnnuel(); } return total; }
Tu avais trouvé ?
Exercice de synthèse 5 : questions de cours
Exercice 5 sur 5 Dix questions rapides Réussi À revoir
Réponds en une ou deux phrases.
- Différence entre une classe et un objet ?
- À quoi sert un constructeur ?
- Qu'est-ce que l'encapsulation, et comment la met-on en œuvre en C# ?
- Différence entre
privateetprotected? - Différence entre surcharge et redéfinition ?
- Pourquoi ne peut-on pas instancier une interface ?
- Quand préférer une interface à une classe abstraite ?
- Différence entre agrégation et composition ?
- Pourquoi redéfinir
GetHashCodeen même temps qu'Equals? - Qu'est-ce que l'injection de dépendances, et à quoi sert-elle ?
Voir la réponseMasquer la réponse de l'exercice 5
- Une classe est un plan qui décrit des données et des méthodes ; un objet est un exemplaire créé à partir de ce plan avec
new, qui a ses propres valeurs. - Il initialise un objet au moment de sa création et garantit qu'il naît valide, en exigeant et en vérifiant les données obligatoires.
- Cacher les données d'un objet et n'y donner accès que par des membres qui contrôlent : champs
private, propriétés avec unsetqui valide ou absent, méthodes métier. - Un membre
privaten'est accessible que dans sa classe ; un membreprotectedl'est aussi dans les classes filles. - La surcharge, ce sont plusieurs méthodes de même nom avec des paramètres différents, choisies à la compilation ; la redéfinition, c'est une classe fille qui remplace (
override) une méthodevirtualde même signature, choisie à l'exécution selon l'objet réel. - Une interface n'est qu'un contrat, sans implémentation ni état : il n'y a rien à construire. On instancie une classe qui l'implémente.
- Quand on veut exprimer une capacité partagée par des classes sans lien de nature, ou permettre à une classe d'en adopter plusieurs ; la classe abstraite convient à une famille d'objets qui partagent un état et du code.
- Dans les deux cas, un tout contient des parties ; dans une composition, les parties n'existent pas sans le tout et disparaissent avec lui (un ticket et ses interventions), dans une agrégation, elles lui survivent (un service et ses employés).
DictionaryetHashSetrangent les objets d'après leur code de hachage avant de les comparer avecEquals: deux objets égaux doivent avoir le même code, sinon ils ne sont jamais comparés et les recherches échouent.- Fournir à une classe, par son constructeur, les objets dont elle dépend, au lieu de la laisser les créer ; elle ne dépend plus que d'interfaces, ce qui permet de changer d'implémentation (MySQL, mémoire) et de la tester avec des doublures.
Tu avais trouvé ?
Aide-mémoire : la syntaxe objet de C#
| Besoin | Syntaxe C# |
|---|---|
| Déclarer une classe | public class Ticket { … } |
| Champ privé en lecture seule | private readonly List<Intervention> interventions = new(); |
| Propriété avec validation | public int Duree { get => duree; set { if (value <= 0) throw …; duree = value; } } |
| Propriété en lecture seule | public string Titre { get; } |
| Propriété modifiable seulement par la classe | public Statut Statut { get; private set; } |
| Propriété calculée | public int Total => interventions.Sum(i => i.DureeMin); |
| Constructeur | public Ticket(string titre) { Titre = titre; } |
| Chaîner les constructeurs | public Ticket(string titre) : this(titre, Priorite.Normale) { } |
| Membre statique | public static int NbCrees { get; private set; } |
| Hériter et appeler le constructeur parent | class Portable : Poste { public Portable(…) : base(…) { } } |
| Méthode redéfinissable / redéfinie | public virtual int Duree => 5; / public override int Duree => 3; |
| Appeler la version parente | base.ToString() |
| Classe et méthode abstraites | abstract class Materiel { public abstract string Description(); } |
| Interface | interface IExportableCsv { string LigneCsv(); } |
| Implémenter plusieurs interfaces | class Materiel : IExportableCsv, IComparable<Materiel> |
| Tester le type | if (m is Poste p) { … }, m as Poste, (Poste)m |
| Égalité métier | Equals(object?) + GetHashCode() + IEquatable<T> |
| Objet-valeur immuable | record Adresse(string Rue, string CodePostal, string Ville); |
| Exception personnalisée | class LicencesEpuiseesException : Exception { public LicencesEpuiseesException(string m) : base(m) { } } |
| Lever, attraper | throw new …; / try { } catch (TypeException e) { } finally { } |
| Libérer une ressource | using MySqlConnection cnx = new(chaine); |
| Événement | public event EventHandler<T>? Change; puis Change?.Invoke(this, e); et objet.Change += …; |
| Attribut | [Required], [Obsolete("…")], [Fact] |
Aide-mémoire : du diagramme UML au code C#
| En UML | En C# |
|---|---|
- nom : string | private string nom; (ou une propriété privée) |
+ Resoudre(date : DateTime) : void | public void Resoudre(DateTime date) |
# enReparation : bool | protected bool EnReparation { get; set; } |
| membre souligné | static |
nom en italique ou {abstract} | abstract |
«interface» | interface |
association de multiplicité 1 | propriété non nullable, exigée par le constructeur |
association 0..1 | propriété nullable : Employe? Utilisateur |
association * ou 0..* | private readonly List<T> + IReadOnlyList<T> + méthodes d'ajout |
| composition (losange plein) | le tout crée ses parties dans ses méthodes |
| classe d'association | une classe qui référence les deux objets et porte les données du lien |
| généralisation (flèche pleine à triangle vide) | class Fille : Mere |
| réalisation (flèche en pointillés à triangle vide) | class Classe : IInterface |
Aide-mémoire : le vocabulaire
| Terme | Définition courte |
|---|---|
| Classe | plan qui décrit les données et les méthodes d'un type d'objets |
| Objet, instance | exemplaire d'une classe, créé avec new |
| Membre | champ, propriété, méthode, constructeur ou événement d'une classe |
| Encapsulation | cacher les données, n'exposer que des accès contrôlés |
| Héritage | une classe fille reçoit les membres de sa classe mère et les spécialise |
| Polymorphisme | un même appel produit un comportement adapté à l'objet réel |
| Abstraction | manipuler un concept (classe abstraite, interface) sans dépendre des détails |
| Liaison dynamique | choix, à l'exécution, de la version d'une méthode virtual à exécuter |
| Surcharge | plusieurs méthodes de même nom, aux paramètres différents |
| Redéfinition | une classe fille remplace une méthode virtual de sa mère avec override |
| Interface | contrat de méthodes qu'une classe s'engage à fournir |
| Généricité | code écrit une fois pour un type paramètre T |
| Patron de conception | solution nommée et éprouvée à un problème de conception récurrent |
| Injection de dépendances | fournir à un objet, de l'extérieur, les objets dont il dépend |
| Attribut (annotation) | métadonnée entre crochets, lue par le compilateur ou un framework |
| Invariant | règle toujours vraie pour un objet valide |
| Couplage, cohésion | dépendance entre classes (à réduire), unité d'une classe (à renforcer) |