Étudiant en RDC suivant un cours sur l'algorithmique et la programmation orientée objet.

Éléments d'algorithmique et de programmation orientée objet

Programmation orientée objet pour concevoir des applications structurelles ultra performantes.

Édition 2026 – Réforme LMD – Enseignement supérieur et universitaire en RDC.

  • Code Officiel : ALP1111,
  • Domaine : Domaine de Sciences Economiques et de Gestion
  • Filière : Informatique de Gestion
  • Année d’étude : LICENCE 1
  • Diplôme attendu : [Bachelor en Sciences de Gestion
Voir la suite de la fiche
  • Mention : Informatique Appliquée à la Gestion des Entreprises
  • Semestre : Semestre 1
  • Crédits totaux : Non spécifié
  • Détail des EC :
    • [1 EC : Éléments d'algorithmique et de programmation orientée objet (Crédits : 6
    • CM : 30h
    • TD : 30h
    • TP : 30h
    • Total présentiel : 90h
    • TPE : 60h)
    • Pas d'options]
  • Volume Horaire : CMI : [30]h, TD : [30]h, TP : [30]h, Total présentiel : [90]h

🎯 Compétences visées :

  • [Mettre en place une application desktop

💼 Métiers cibles :

  • [Technicien supérieur en informatique
  • Analyste d'affaires
  • Développeur d'applications desktop
  • Développeur web]

PRÉLIMINAIRES

I. Fiche signalétique de l’Unité d’Enseignement (UE)

Cette Unité d’Enseignement, codifiée ALP1111, s’intitule “Éléments d’algorithmique et de programmation orientée objet”. Ancrée dans le Domaine des Sciences Économiques et de Gestion, elle est fondamentale pour la filière Informatique de Gestion (Mention : Informatique Appliquée à la Gestion des Entreprises). Dispensée en Licence 1 (Semestre 1), elle représente 6 crédits pour un volume horaire global de 150h, incluant 90h en présentiel (30h CM, 30h TD, 30h TP) et 60h de Travail Personnel de l’Étudiant (TPE).

II. Compétences visées et débouchés professionnels

L’objectif terminal est la maîtrise de la conception et de l’implémentation d’applications desktop structurées. Cette compétence fondamentale ouvre la voie à des carrières de Technicien supérieur en informatique, capable de maintenir et faire évoluer des parcs logiciels. Elle prépare également aux fonctions d’Analyste d’affaires junior, apte à traduire les besoins métier en spécifications techniques, et de Développeur d’applications desktop ou web, acteur clé de la transformation numérique des entreprises congolaises.

III. Problématique et pertinence socio-économique pour la RDC

Face à l’impératif de digitalisation de l’économie congolaise, la maîtrise de la programmation structurée n’est plus une option mais une nécessité stratégique. Cette UE répond au besoin criant de compétences locales capables de développer des solutions sur mesure : gestion de stocks pour les PME de Matadi, suivi des patients pour les centres de santé de Goma, ou applications de micro-crédit à Kinshasa. Former des développeurs autonomes, c’est bâtir les fondations d’une souveraineté numérique nationale.

IV. Approche pédagogique et modalités d’évaluation

Une pédagogie active par projet structure cette UE. Les Cours Magistraux (CM) posent les fondements théoriques. Les Travaux Dirigés (TD) les consolident par des exercices ciblés. Les Travaux Pratiques (TP) exigent la production de code fonctionnel pour résoudre des problèmes concrets issus du tissu économique local. L’évaluation combine un contrôle continu (projets, interrogations) et un examen final pratique, validant la capacité de l’étudiant à livrer une application fonctionnelle et documentée.

PARTIE 1 : Éléments d’algorithmique et de programmation orientée objet

Chapitre I. Fondements de la pensée algorithmique

I.1 Définition et nature d’un algorithme

Au cœur de toute solution informatique, l’algorithme se définit comme une suite finie et non-ambiguë d’opérations permettant de résoudre un problème donné. Cette section formalise cette notion en la distinguant d’une simple recette. L’étudiant apprendra à décomposer un besoin métier, comme le calcul des taxes sur les ventes à Kinshasa, en une séquence logique d’instructions exécutables par une machine, garantissant un résultat prévisible et correct.

I.2 Propriétés fondamentales d’un algorithme

Sous l’angle de la rigueur, tout algorithme doit posséder des qualités intrinsèques : finitude, précision, entrées et sorties définies. Analyser ces propriétés est crucial pour garantir la robustesse d’une application. Nous étudions ici comment la validation de ces critères avant même l’écriture du code permet d’éviter des erreurs critiques, notamment dans des systèmes de gestion où la fiabilité des transactions (ex: M-Pesa, Airtel Money) est non-négociable.

I.3 De la problématique métier à la spécification algorithmique

Une compréhension fine du processus de traduction d’un besoin utilisateur en une logique formelle est la première étape du génie logiciel. Ce point détaille la méthodologie d’analyse fonctionnelle : identifier les données d’entrée, les traitements à effectuer et les résultats attendus. L’application pratique portera sur la modélisation du processus d’inscription d’un nouvel abonné pour une compagnie de distribution d’eau, un cas d’usage courant en RDC.

I.4 Outils de représentation : Pseudo-code et organigrammes

Face à la complexité, la visualisation est un outil cognitif puissant. Le pseudo-code (langage structuré) et les organigrammes (représentation graphique) sont les deux instruments normalisés pour décrire un algorithme indépendamment de tout langage de programmation. Leur maîtrise assure une communication claire au sein d’une équipe de développement et facilite la maintenance future du code, un enjeu majeur pour la pérennité des projets informatiques locaux.

Chapitre II. Variables, Types de données et Opérateurs

II.1 Le concept de variable et la gestion de la mémoire

Pivot de la programmation, la variable est un conteneur symbolique d’information. Cette section démystifie son fonctionnement en lien avec l’allocation mémoire de l’ordinateur. Comprendre la déclaration, l’initialisation et la portée d’une variable est le prérequis pour manipuler correctement les données, qu’il s’agisse du prix d’un sac de ciment, du nom d’un client ou du stock de médicaments dans une pharmacie de Lubumbashi.

II.2 Typage des données : Une contrainte pour la robustesse

Imposer un type à une donnée (entier, réel, chaîne de caractères, booléen) n’est pas une limitation mais une garantie de cohérence. Nous explorons ici la taxonomie des types primitifs et leur utilité pour prévenir les erreurs de calcul ou de logique. Un typage rigoureux est essentiel pour assurer l’intégrité des données dans une base de données de gestion des ressources humaines ou un système de facturation pour une PME congolaise.

II.3 Opérateurs : Le moteur de la transformation des données

Les opérateurs arithmétiques, relationnels et logiques constituent l’arsenal permettant d’effectuer des calculs et de prendre des décisions. Cette section présente leur syntaxe, leur priorité et leur application dans la construction d’expressions complexes. Maîtriser les opérateurs est indispensable pour implémenter des règles de gestion, comme le calcul d’une remise en fonction d’une quantité commandée ou la validation des droits d’accès d’un utilisateur.

II.4 Expressions, affectation et lecture/écriture

Une connaissance approfondie des mécanismes d’évaluation des expressions et du processus d’affectation est cruciale pour contrôler le flux des données. Ce sous-chapitre détaille comment le programme reçoit des informations (lecture depuis le clavier ou un fichier) et communique des résultats (écriture à l’écran). Ces opérations d’entrée/sortie sont la base de toute interaction homme-machine, de la simple caisse enregistreuse au logiciel de gestion intégrée.

Chapitre III. Les structures de contrôle conditionnelles

III.1 La structure alternative simple : SI… ALORS… SINON

Face à une décision, l’instruction IF...THEN...ELSE est le mécanisme fondamental pour orienter l’exécution du programme. Son étude permet de modéliser des choix binaires omniprésents dans la gestion. Par exemple, déterminer si un étudiant a validé un cours en fonction de sa note, ou appliquer une tarification différente pour un client résident ou non-résident. La maîtrise de cette structure est la première étape vers un code intelligent.

III.2 Imbrication des conditions pour une logique fine

La réalité des affaires est rarement binaire. L’imbrication de structures conditionnelles permet de gérer des scénarios à choix multiples et complexes. Nous analysons ici comment construire des arbres de décision logiques et lisibles pour traiter des cas comme la catégorisation d’un produit en fonction de multiples critères (poids, fragilité, destination) afin d’optimiser la logistique de transport sur l’axe Matadi-Kinshasa.

III.3 La structure de sélection multiple : SELON LE CAS

Pour des décisions basées sur les multiples valeurs possibles d’une seule variable, la structure SWITCH...CASE (ou équivalent) offre une alternative plus élégante et performante que des IF imbriqués. Ce point démontre son efficacité pour implémenter des menus interactifs, router des requêtes en fonction d’un code d’opération, ou encore affecter un statut à une commande (en attente, validée, expédiée, livrée).

III.4 Opérateurs logiques et conditions composées

La puissance des structures conditionnelles est décuplée par l’utilisation des opérateurs logiques (ET, OU, NON) pour formuler des prédicats complexes. Cette section se concentre sur l’art de combiner plusieurs conditions pour refléter fidèlement des règles de gestion sophistiquées. Par exemple, accorder un prêt si le client est solvable ET a un historique de paiement positif OU s’il fournit une garantie suffisante.

Chapitre IV. Les structures de contrôle itératives

IV.1 La boucle TANT QUE : Itération contrôlée par une condition

Indispensable pour les traitements dont le nombre de répétitions est inconnu à l’avance, la boucle WHILE exécute un bloc d’instructions tant qu’une condition reste vraie. Son application est cruciale pour des tâches comme la validation de la saisie d’un utilisateur jusqu’à ce qu’elle soit correcte, ou le traitement des transactions d’un fichier jusqu’à sa fin. C’est le pilier de la programmation événementielle et interactive.

IV.2 La boucle POUR : Itération sur une séquence finie

D’une importance capitale pour le traitement de collections de données, la boucle FOR permet de parcourir un ensemble d’éléments de taille connue (plage de nombres, jours de la semaine, articles d’un inventaire). Nous étudions sa syntaxe et son usage optimisé pour des opérations systématiques, comme le calcul du chiffre d’affaires total en additionnant les ventes de chaque produit dans un entrepôt de la Gombe.

IV.3 Boucles imbriquées et traitement de données tabulaires

La combinaison de boucles est la technique standard pour manipuler des structures de données à deux dimensions, comme des tableaux ou des grilles. Ce sous-chapitre explore comment des boucles imbriquées permettent de parcourir ligne par ligne et colonne par colonne une matrice de données, une opération fondamentale pour générer des relevés de notes, des calendriers ou pour traiter des images pixel par pixel.

IV.4 Stratégies de sortie de boucle et contrôle du flux

Parfois, une itération doit se terminer prématurément (instruction break) ou passer directement à l’itération suivante (instruction continue). La maîtrise de ces instructions de contrôle de flux est essentielle pour écrire un code efficace et gérer les cas exceptionnels sans complexifier la logique principale. Leur usage est illustré dans des algorithmes de recherche où le traitement s’arrête dès que l’élément est trouvé.

Chapitre V. Les Tableaux et Structures de données statiques

V.1 Le tableau à une dimension : Vecteurs

Le tableau est la structure de données fondamentale pour stocker une collection d’éléments de même type. Ce point couvre la déclaration, l’initialisation et l’accès aux éléments par leur indice. L’étudiant apprendra à manipuler des listes de prix, des relevés de température, ou des scores de candidats, démontrant comment les tableaux permettent de traiter en masse des informations homogènes, une nécessité pour toute application de gestion.

V.2 Le tableau à deux dimensions : Matrices

Extension logique du vecteur, la matrice permet de représenter des données tabulaires comme des grilles, des emplois du temps ou des plans comptables. Nous abordons ici les techniques de parcours et de manipulation de ces structures. L’application pratique consistera à modéliser et interroger un tableau de distances entre les principales villes de la RDC pour préparer des algorithmes d’optimisation logistique.

V.3 Les chaînes de caractères comme tableaux spécialisés

Sous l’angle de la manipulation de texte, les chaînes de caractères sont souvent implémentées comme des tableaux de caractères. Cette section explore les opérations spécifiques à ce type de données : concaténation, extraction de sous-chaînes, recherche de motifs. Ces compétences sont vitales pour traiter les noms, adresses, descriptions de produits et toute autre information textuelle au sein des systèmes d’information d’entreprise.

V.4 Les structures et enregistrements : Agrégation de types hétérogènes

Face au besoin de regrouper des informations de types différents relatives à une même entité (ex: pour un Employé : nom, âge, salaire), la structure ou l’ enregistrement est la solution. Ce concept est le précurseur direct de l’objet en POO. Nous montrons comment il permet de créer des types de données personnalisés qui modélisent fidèlement les entités du monde réel, comme une fiche produit ou un dossier client.

Chapitre VI. Les Fonctions et la Programmation modulaire

VI.1 Décomposition fonctionnelle d’un problème

En réponse à la complexité, la stratégie “diviser pour régner” est universelle. En programmation, elle se traduit par la décomposition d’un programme en sous-programmes ou fonctions, chacun responsable d’une tâche unique et bien définie. Cette section enseigne l’art d’identifier ces modules logiques pour transformer un problème monolithique en un ensemble de sous-problèmes gérables, améliorant la clarté et la maintenabilité.

VI.2 Définition et appel de fonctions : Paramètres et valeur de retour

Une fonction est une boîte noire qui reçoit des données en entrée (paramètres) et produit un résultat (valeur de retour). Ce point technique détaille la syntaxe de définition et d’appel, en insistant sur la signature de la fonction (son contrat). Maîtriser ce mécanisme est essentiel pour créer du code réutilisable, par exemple une fonction calculerTVA qui peut être appelée depuis n’importe où dans une application commerciale.

VI.3 Portée des variables : Variables locales vs. globales

Une connaissance rigoureuse de la portée des variables (locales à une fonction ou globales au programme) est impérative pour éviter des effets de bord et des bugs difficiles à tracer. Nous analysons ici les règles de visibilité et la durée de vie des variables pour promouvoir l’encapsulation et la création de fonctions autonomes et fiables, un principe clé de l’ingénierie logicielle robuste.

VI.4 Passage de paramètres : Par valeur vs. par référence

Le mode de passage des paramètres (copie de la valeur ou transmission de l’adresse mémoire) a des implications profondes sur la performance et le comportement du programme. Cette section compare les deux mécanismes et leurs cas d’usage respectifs. Comprendre cette distinction est crucial lors de la manipulation de grandes structures de données, afin d’éviter des copies inutiles qui ralentiraient une application de traitement de données agricoles.

Chapitre VII. Introduction à la Programmation Orientée Objet (POO)

VII.1 Limites de l’approche procédurale et genèse de la POO

L’approche procédurale, bien que puissante, montre ses limites face à la complexité croissante des logiciels. Ce sous-chapitre analyse ces faiblesses (gestion des données globale, faible réutilisabilité) et introduit la POO comme un changement de paradigme. La POO propose de modéliser le monde non plus en termes de procédures, mais en termes d’objets interactifs, une approche plus intuitive pour représenter les entités d’un système de gestion.

VII.2 Le concept de classe : Moule à objets

D’origine conceptuelle, la classe est le plan de construction, la matrice qui définit la structure (attributs) et le comportement (méthodes) d’une catégorie d’objets. Nous étudions ici comment concevoir une classe CompteBancaire avec ses attributs (solde, titulaire) et ses méthodes (déposer, retirer). Cette abstraction est la pierre angulaire de la POO, permettant de créer des modèles logiciels cohérents et extensibles.

VII.3 L’objet : Instance d’une classe

Un objet est la matérialisation concrète d’une classe en mémoire, avec son propre état. À partir d’une seule classe Voiture, on peut créer de multiples objets : maVoiture, voitureDeService, chacun avec ses propres valeurs d’attributs (couleur, kilométrage). Cette section clarifie la relation vitale entre classe et objet, qui est au cœur de la capacité de la POO à gérer de multiples entités similaires mais distinctes.

VII.4 Attributs et Méthodes : État et Comportement

La dualité attributs/méthodes est fondamentale. Les attributs (variables d’instance) définissent l’état d’un objet, tandis que les méthodes (fonctions d’instance) définissent son comportement et la manière dont il peut interagir avec le monde extérieur. Nous analysons comment cette union au sein de l’objet permet de garantir que les données ne sont manipulées qu’à travers des opérations contrôlées, assurant l’intégrité du modèle.

Chapitre VIII. Le pilier de l’encapsulation

VIII.1 Principe de masquage de l’information

L’encapsulation est un principe de protection qui consiste à cacher les détails d’implémentation d’un objet et à n’exposer qu’une interface publique contrôlée. Ce mécanisme prévient les manipulations directes et non autorisées de l’état interne d’un objet. Appliquer ce principe est vital pour construire des composants logiciels robustes et fiables, à l’image d’un guichet automatique qui ne donne accès qu’à des opérations bancaires validées.

VIII.2 Niveaux de visibilité : Public, Privé, Protégé

Pour implémenter l’encapsulation, les langages POO fournissent des modificateurs d’accès (public, private, protected). Cette section détaille la sémantique de chaque niveau de visibilité et leur impact sur l’architecture logicielle. Une utilisation judicieuse de ces modificateurs est la marque d’une conception professionnelle, garantissant que chaque partie du code n’a accès qu’aux informations qui lui sont strictement nécessaires.

VIII.3 Accesseurs (Getters) et Mutateurs (Setters)

Afin de permettre un accès contrôlé aux attributs privés, on utilise des méthodes publiques spécifiques : les accesseurs (pour lire une valeur) et les mutateurs (pour la modifier). Ce point technique montre comment l’implémentation de getters et setters permet d’insérer de la logique de validation (ex: un solde ne peut être négatif), transformant de simples affectations en opérations métier sécurisées.

VIII.4 Le constructeur : Initialisation contrôlée de l’objet

Le constructeur est une méthode spéciale, appelée automatiquement lors de la création d’un objet, dont le rôle est d’assurer son initialisation correcte. Maîtriser les constructeurs est essentiel pour garantir que chaque objet est créé dans un état initial valide et cohérent. Nous étudions comment définir des constructeurs pour initialiser, par exemple, un objet Facture avec un numéro unique et une date système.

Chapitre IX. Le pilier de l’héritage

IX.1 Principe de spécialisation et de généralisation

L’héritage est le mécanisme qui permet à une classe (dite fille) d’acquérir les attributs et méthodes d’une autre classe (dite mère), créant une relation “est un type de”. Ce puissant concept favorise la réutilisation du code et l’organisation hiérarchique des connaissances. Nous modélisons ici une hiérarchie de Personne -> Etudiant / Enseignant, où les classes filles spécialisent le concept général de Personne.

IX.2 Implémentation de l’héritage simple

Ce sous-chapitre technique se concentre sur la syntaxe et les mécanismes de l’héritage simple. L’étudiant apprendra à déclarer une classe qui hérite d’une autre et à observer comment les propriétés de la classe de base sont automatiquement disponibles dans la classe dérivée. L’exemple portera sur la création de différentes classes de véhicules (Camion, Bus) héritant toutes d’une classe de base Vehicule partageant des attributs communs.

IX.3 Redéfinition de méthodes (Overriding)

Une classe fille peut fournir sa propre implémentation pour une méthode héritée de sa classe mère. Ce mécanisme, appelé redéfinition, permet d’adapter le comportement d’une méthode au contexte plus spécifique de la classe fille. Par exemple, la méthode calculerSalaire() sera différente pour un Cadre et pour un Ouvrier, bien que les deux soient des Employes.

IX.4 Classes abstraites et méthodes abstraites

Une classe abstraite est un modèle incomplet qui ne peut être instancié directement. Elle sert de base pour d’autres classes et peut définir des méthodes abstraites (sans corps) que ses classes filles seront obligées d’implémenter. Ce concept est crucial pour définir des contrats d’interface et forcer une structure commune à toute une famille de classes, garantissant une certaine homogénéité dans l’architecture logicielle.

Chapitre X. Le pilier du polymorphisme

X.1 Définition et manifestation du polymorphisme

Le polymorphisme (“plusieurs formes”) est la capacité d’un objet à prendre plusieurs types, typiquement son propre type et celui de ses classes parentes. Il permet de manipuler des objets de types différents via une interface commune. Cette section explique comment, grâce au polymorphisme, on peut stocker dans une même liste des Chiens et des Chats et appeler sur chacun la méthode crier(), qui produira un son différent.

X.2 Liaison tardive (Dynamic Binding)

La liaison tardive est le mécanisme technique qui rend le polymorphisme possible. C’est la capacité du système à déterminer au moment de l’exécution, et non à la compilation, quelle version spécifique d’une méthode redéfinie doit être appelée. Comprendre ce concept est essentiel pour saisir la flexibilité et la puissance des systèmes orientés objet, capables de s’adapter dynamiquement à différents types de données.

X.3 Interfaces : Un contrat de comportement pur

Une interface est une collection de signatures de méthodes abstraites, définissant un contrat de comportement qu’une classe peut s’engager à respecter. Contrairement à l’héritage, une classe peut implémenter plusieurs interfaces. C’est un outil de conception extrêmement puissant pour découpler les composants logiciels, comme définir une interface Payable que pourront implémenter les classes Facture et Salaire.

X.4 Application du polymorphisme dans les collections

La véritable puissance du polymorphisme se révèle dans la gestion de collections hétérogènes. Ce point démontre comment il est possible de créer une liste d’objets FormeGeometrique contenant des Cercles, Rectangles et Triangles, et de calculer l’aire totale en parcourant la liste et en appelant la méthode calculerAire() sur chaque objet, sans jamais avoir à tester son type spécifique.

Chapitre XI. Algorithmes de tri et de recherche fondamentaux

XI.1 Complexité algorithmique : Introduction à la notation Big O

Avant d’étudier les algorithmes, il est crucial d’avoir un outil pour mesurer leur efficacité. La notation “Grand O” permet de caractériser la performance d’un algorithme (en temps et en espace) en fonction de la taille des
données d’entrée. Cette mesure est généralement exprimée à l’aide de la notation Grand O (Big O).

La notation Grand O ne mesure pas le temps d’exécution exact en secondes, mais plutôt l’ordre de grandeur de la croissance du nombre d’opérations. Elle décrit le pire scénario (cas le plus défavorable) pour un algorithme.

Voici quelques-unes des complexités les plus courantes, classées de la plus efficace à la moins efficace :

  • O(1) – Complexité constante : Le temps d’exécution est constant et ne dépend pas de la taille des données.

    • Exemple : Accéder à un élément d’un tableau par son index.
  • O(log n) – Complexité logarithmique : Le temps d’exécution augmente de manière logarithmique avec la taille des données. L’algorithme devient légèrement plus lent à mesure que les données augmentent.

    • Exemple : La recherche dichotomique (binary search) dans un tableau trié.
  • O(n) – Complexité linéaire : Le temps d’exécution est directement proportionnel à la taille des données. Si la taille des données double, le temps d’exécution double également.

    • Exemple : Parcourir tous les éléments d’une liste pour trouver une valeur.
  • O(n log n) – Complexité quasi-linéaire (ou log-linéaire) : C’est une performance très courante pour les algorithmes de tri efficaces.

    • Exemple : Le tri fusion (merge sort) ou le tri rapide (quicksort).
  • O(n²) – Complexité quadratique : Le temps d’exécution est proportionnel au carré de la taille des données. Ces algorithmes deviennent rapidement lents lorsque la taille des données augmente.

    • Exemple : Des boucles imbriquées qui parcourent deux fois la même collection de données, comme dans un tri à bulles simple.
  • O(2ⁿ) – Complexité exponentielle : Le temps d’exécution double à chaque nouvel élément ajouté aux données. Ces algorithmes sont extrêmement lents et ne sont pratiques que pour de très petites tailles de données.

    • Exemple : La résolution récursive du problème des tours de Hanoï.
  • O(n!) – Complexité factorielle : Le temps d’exécution croît de manière factorielle. C’est l’une des pires complexités, rendant l’algorithme inutilisable pour tout sauf les plus petits ensembles de données.

    • Exemple : La résolution du problème du voyageur de commerce par une approche de force brute.

Comprendre la complexité algorithmique est essentiel pour choisir la bonne structure de données et le bon algorithme pour un problème donné, afin de garantir que l’application reste performante et évolutive.

PARTIE 1 : Éléments d’algorithmique et de programmation orientée objet

Chapitre I. Fondements de la pensée algorithmique

I.1 Déconstruction du problème et abstraction

Au cœur de toute solution informatique réside la capacité à décomposer un problème complexe en sous-problèmes gérables. Cette section instruit sur les techniques formelles d’analyse et d’abstraction pour isoler les composantes essentielles d’un cahier des charges. L’étudiant apprendra à modéliser des processus métiers congolais, comme la gestion des stocks d’une pharmacie à Kinshasa ou le suivi de la production agricole dans le Kwilu, en une suite logique d’opérations élémentaires, préparant le terrain pour une traduction informatique rigoureuse.

I.2 Structures de contrôle séquentielles, conditionnelles et itératives

Pivot de la logique programmatique, la maîtrise des structures de contrôle détermine la fluidité et la pertinence d’un algorithme. Ce point détaille l’implémentation de la séquence, du choix (si/sinon) et de la répétition (boucles pour/tant que) comme outils de base pour diriger le flux d’exécution. L’application pratique se concentre sur l’automatisation de tâches administratives, telles que le calcul des salaires selon l’ancienneté ou la validation des inscriptions universitaires en RDC, en fonction de critères multiples.

I.3 Représentation formelle : du pseudo-code aux organigrammes

Une communication sans ambiguïté de la logique algorithmique est impérative avant toute écriture de code. Ce sous-chapitre enseigne les deux langages de description universels : le pseudo-code, proche du langage naturel structuré, et les organigrammes, représentation graphique des flux. L’objectif est de permettre aux futurs analystes de documenter et de valider une solution, par exemple le processus d’octroi d’un micro-crédit à Goma, de manière compréhensible par les parties prenantes techniques et non techniques.

I.4 Analyse de la complexité : introduction aux notations de Landauer

Face à l’explosion des volumes de données, l’efficacité d’un algorithme n’est plus une option. Cette section introduit l’analyse de la complexité temporelle et spatiale, en utilisant les notations de Landauer (O, Ω, Θ) pour quantifier la performance d’un algorithme indépendamment de la machine. L’étudiant évaluera pourquoi un algorithme de tri est préférable à un autre pour traiter des millions de transactions d’un opérateur de mobile money en RDC, garantissant une expérience utilisateur fluide.

Chapitre II. Structures de données statiques et manipulation

II.1 Tableaux unidimensionnels et multidimensionnels

Fondation de l’organisation des données en mémoire, le tableau est la structure la plus élémentaire et la plus utilisée. Ce point explore la déclaration, l’initialisation et la manipulation de tableaux à une et plusieurs dimensions pour stocker des collections homogènes de données. Les cas d’usage portent sur la modélisation de grilles, comme un plan de salle de classe, ou la représentation de données tabulaires, tel le relevé des prix des denrées sur les marchés de Lubumbashi.

II.2 Algorithmes de tri fondamentaux : bulles, sélection, insertion

Une organisation efficiente des données est une condition sine qua non à leur exploitation. Ce sous-chapitre présente et analyse les algorithmes de tri les plus didactiques : tri à bulles, par sélection et par insertion. Bien que non optimaux pour de grands volumes, leur étude est cruciale pour comprendre les mécanismes d’échanges et de comparaisons. L’étudiant implémentera ces tris pour classer une liste de clients d’une PME congolaise par ordre alphabétique ou par chiffre d’affaires.

II.3 Algorithmes de recherche : séquentielle et dichotomique

Retrouver une information spécifique au sein d’un vaste ensemble de données est une opération courante et critique. Cette section oppose la recherche séquentielle, simple mais lente, à la recherche dichotomique, extrêmement rapide mais exigeant des données triées. L’application se concentre sur la recherche d’un numéro de parcelle dans le cadastre national ou la vérification de la disponibilité d’un produit dans un inventaire informatisé, démontrant l’impact direct de l’algorithme sur la performance.

II.4 Chaînes de caractères et opérations textuelles

Dans une économie de plus en plus numérisée, la manipulation de l’information textuelle est omniprésente. Ce point couvre les opérations fondamentales sur les chaînes de caractères : concaténation, extraction de sous-chaînes, recherche et remplacement. Les compétences acquises sont directement applicables au traitement de formulaires en ligne, à l’analyse de messages SMS pour des services d’alerte agricole, ou à la validation de formats de données comme les numéros de téléphone ou les adresses e-mail en RDC.

Chapitre III. Le paradigme de la Programmation Orientée Objet (POO)

III.1 Rupture paradigmatique : de la procédure à l’objet

Marquant une évolution majeure dans la conception logicielle, le passage de la programmation procédurale à l’orienté objet change la perspective du développeur. Ici, nous analysons comment la POO modélise le monde réel en termes d’objets interagissant, plutôt qu’en une suite d’instructions. L’étudiant saisira comment conceptualiser une application de gestion bancaire en RDC non pas comme des fonctions, mais comme des objets “Client”, “Compte”, “Transaction”, favorisant une structure plus intuitive et maintenable.

III.2 Encapsulation : protection des données et interface publique

Principe fondateur de la POO, l’encapsulation consiste à lier les données (attributs) et les opérations qui les manipulent (méthodes) au sein d’un même objet, tout en masquant les détails d’implémentation. Cette section démontre comment ce mécanisme protège l’intégrité des données. Un objet “CompteBancaire” n’exposera qu’une méthode deposer(montant) et non son solde directement, empêchant ainsi toute modification arbitraire et garantissant la robustesse des applications financières développées en RDC.

III.3 Abstraction : modélisation de l’essentiel

L’abstraction permet de se concentrer sur les caractéristiques pertinentes d’un objet tout en ignorant les détails non essentiels. Ce sous-chapitre enseigne comment définir des “contrats” conceptuels pour les objets. Pour un système logistique gérant le transport sur le fleuve Congo, un objet “Barge” sera abstrait par sa capacité de chargement et sa vitesse, et non par la couleur de sa coque, permettant de créer des modèles logiciels clairs et focalisés sur la résolution du problème métier.

III.4 Classes et Objets : de la conception (blueprint) à l’instance

La distinction entre classe et objet est au cœur de la POO. La classe est le plan de construction (le “blueprint”), tandis que l’objet est l’exemplaire concret (l’instance) créé à partir de ce plan. Nous illustrons ce concept en définissant une classe Etudiant avec des attributs (nom, matricule) et des méthodes (s_inscrire_au_cours). Chaque étudiant réel de l’UNIKIN devient alors une instance unique de cette classe, chacune avec ses propres valeurs d’attributs.

Chapitre IV. Piliers de la POO : Héritage et Polymorphisme

IV.1 Héritage : réutilisation et spécialisation du code

L’héritage est le mécanisme qui permet à une nouvelle classe de réutiliser, d’étendre ou de modifier le comportement d’une classe existante. Cette section explore la création de hiérarchies de classes pour factoriser le code et modéliser des relations “est un”. Par exemple, en RDC, les classes CompteCourant et CompteEpargne peuvent hériter d’une classe de base CompteBancaire, favorisant la réutilisation du code et réduisant drastiquement le temps de développement et les risques d’erreurs.

IV.2 Polymorphisme : une interface, plusieurs comportements

Concept puissant, le polymorphisme permet de manipuler des objets de types différents via une interface commune. Ce point démontre comment un même appel de méthode peut déclencher des comportements différents selon le type de l’objet. Une fonction calculerImpot() pourra s’appliquer à des objets EntrepriseMiniere, PME ou CommerceDeDetail, chaque objet implémentant sa propre logique de calcul, ce qui simplifie radicalement le code de traitement fiscal pour l’administration congolaise.

IV.3 Classes abstraites et interfaces : les contrats de conception

Au-delà de l’héritage concret, les classes abstraites et les interfaces servent à définir des squelettes de comportement sans les implémenter. Elles agissent comme des contrats qui forcent les classes dérivées à respecter une structure donnée. Nous verrons comment définir une interface IPaiementMobile en RDC, obligeant les classes MPesa, AirtelMoney et OrangeMoney à fournir une méthode effectuerPaiement(), garantissant ainsi leur interchangeabilité dans une application d’e-commerce.

IV.4 Surcharge et redéfinition de méthodes (Overloading vs. Overriding)

La flexibilité du polymorphisme repose sur deux techniques distinctes : la surcharge (overloading) et la redéfinition (overriding). La surcharge permet à plusieurs méthodes de porter le même nom au sein d’une même classe, à condition que leurs paramètres diffèrent. La redéfinition permet à une sous-classe de fournir une implémentation spécifique d’une méthode déjà définie dans sa super-classe. La maîtrise de cette nuance est cruciale pour concevoir des API claires et expressives.

Chapitre V. Application des principes de conception SOLID

V.1 Principe de responsabilité unique (Single Responsibility Principle)

Un design logiciel robuste exige que chaque classe n’ait qu’une seule raison de changer. Ce sous-chapitre martèle l’importance de dédier chaque classe à une unique responsabilité. Dans une application de gestion hospitalière pour la RDC, une classe Patient gère les informations démographiques, tandis qu’une classe DossierMedical gère l’historique des soins. Cette séparation stricte facilite la maintenance et l’évolution du système en isolant les impacts des modifications.

V.2 Principe Ouvert/Fermé (Open/Closed Principle)

Les entités logicielles doivent être ouvertes à l’extension mais fermées à la modification. Ce principe guide la conception de systèmes évolutifs sans réécrire le code existant et testé. Nous étudions comment, via des stratégies comme le pattern Strategy, on peut ajouter de nouvelles règles de calcul de taxes sur les exportations de cobalt sans jamais toucher au module de facturation principal, garantissant la stabilité des systèmes critiques de l’économie congolaise.

V.3 Principe de substitution de Liskov (Liskov Substitution Principle)

Ce principe fondamental garantit la cohérence des hiérarchies d’héritage : un objet d’une classe de base doit pouvoir être remplacé par un objet de n’importe laquelle de ses sous-classes sans altérer la cohérence du programme. Nous analysons des cas concrets, comme s’assurer qu’un objet CamionFrigorifique puisse être utilisé partout où un objet VehiculeDeTransport est attendu dans un système de logistique alimentaire, sans introduire de comportement inattendu.

V.4 Principes de ségrégation d’interface et d’inversion de dépendance

Ces deux derniers principes SOLID visent à découpler les composants logiciels. La ségrégation d’interface (ISP) préconise des interfaces client-spécifiques plutôt que des interfaces générales. L’inversion de dépendance (DIP) stipule que les modules de haut niveau ne doivent pas dépendre des modules de bas niveau. L’application de ces principes permet de construire des architectures modulaires, comme les systèmes d’information du gouvernement, où des composants peuvent être remplacés ou mis à jour indépendamment.

Chapitre VI. Gestion des erreurs et programmation défensive

VI.1 Exceptions : mécanisme de gestion des erreurs d’exécution

Une application robuste doit anticiper et gérer les conditions anormales. Ce point introduit le mécanisme des exceptions (try-catch-finally) comme une méthode structurée pour traiter les erreurs d’exécution, telles qu’une division par zéro ou une connexion réseau perdue lors d’une transaction mobile. L’étudiant apprendra à séparer la logique métier du code de gestion d’erreurs, améliorant la lisibilité et la fiabilité des applications destinées au marché congolais.

VI.2 Création d’exceptions personnalisées

Pour une sémantique d’erreur plus riche, la création d’exceptions personnalisées est essentielle. Ce sous-chapitre montre comment définir ses propres classes d’exception (par ex., SoldeInsuffisantException, MatriculeInvalideException) pour représenter des erreurs spécifiques au domaine d’application. Cette pratique permet de construire des API plus expressives et des systèmes de diagnostic d’erreurs plus précis pour les applications de gestion développées localement.

VI.3 Assertions et contrats : la programmation défensive

Avant même la gestion des erreurs, la programmation défensive vise à prévenir les bugs en validant les états et les entrées. Nous explorons l’utilisation des assertions pour vérifier les invariants du code pendant le développement et le concept de “Design by Contract” pour définir formellement les préconditions, postconditions et invariants des méthodes. Ceci est vital pour construire des logiciels de haute fiabilité, notamment pour le secteur minier ou financier en RDC.

VI.4 Journalisation (Logging) : diagnostic et traçabilité

Lorsqu’une erreur survient en production, une trace de l’événement est indispensable pour le diagnostic. Cette section enseigne les bonnes pratiques de la journalisation (logging) : quels niveaux de logs utiliser (DEBUG, INFO, ERROR), quelles informations enregistrer et comment éviter de surcharger les logs. Un bon logging est crucial pour la maintenance à distance d’applications déployées à travers la RDC, de Matadi à Bukavu, permettant un dépannage efficace sans accès physique.

Chapitre VII. Introduction aux Design Patterns (Modèles de conception)

VII.1 Utilité et classification des Design Patterns

Les Design Patterns sont des solutions éprouvées, réutilisables, à des problèmes de conception logicielle courants. Ce point introduit le concept, son origine (GoF – Gang of Four) et sa classification en trois familles : créationnels, structurels et comportementaux. L’étudiant comprendra que l’utilisation de patterns n’est pas une fin en soi, mais un moyen d’améliorer la flexibilité, l’élégance et la maintenabilité de ses propres conceptions logicielles.

VII.2 Patterns créationnels : Singleton, Factory Method

Les patterns créationnels déchargent le système de la connaissance directe de la manière dont ses objets sont créés. Nous étudions en détail le Singleton, qui garantit une instance unique pour une classe (ex: un gestionnaire de connexion à la base de données), et la Factory Method, qui permet de déléguer la création d’objets à des sous-classes. Cette dernière est utile pour un système de génération de rapports en RDC pouvant produire des PDF, CSV ou Excel.

VII.3 Patterns structurels : Adapter, Decorator, Facade

Les patterns structurels simplifient l’organisation des classes et des objets en de plus grandes structures. L’Adapter permet de faire collaborer des classes aux interfaces incompatibles. Le Decorator ajoute dynamiquement des fonctionnalités à un objet. La Facade fournit une interface unifiée et simplifiée à un sous-système complexe, par exemple en créant une facade ServicePublicEnLigne qui masque la complexité des interactions avec les API des différents ministères congolais.

VII.4 Patterns comportementaux : Observer, Strategy

Les patterns comportementaux gèrent les algorithmes et l’assignation des responsabilités entre objets. L’Observer permet à des objets de s’abonner et d’être notifiés des changements d’état d’un autre objet (ex: mise à jour d’une interface utilisateur quand les données changent). Le Strategy permet de définir une famille d’algorithmes, de les encapsuler et de les rendre interchangeables (ex: choisir dynamiquement une stratégie de livraison à Kinshasa selon le trafic).

Chapitre VIII. Manipulation de fichiers et persistance des données

VIII.1 Flux (Streams) et opérations sur les fichiers binaires et textes

La capacité d’un programme à lire et écrire des données sur un support de stockage permanent est fondamentale. Cette section explore le concept de flux (streams) pour la manipulation de fichiers. L’étudiant apprendra à lire et écrire des fichiers texte ligne par ligne (ex: fichiers de configuration) et des fichiers binaires octet par octet (ex: images, sons), une compétence essentielle pour toute application devant sauvegarder son état ou interagir avec le système de fichiers.

VIII.2 Sérialisation et désérialisation d’objets

La sérialisation est le processus de conversion d’un objet en un format (binaire ou texte) qui peut être stocké ou transmis, puis reconstitué ultérieurement (désérialisation). Ce mécanisme est crucial pour sauvegarder l’état d’une application ou pour communiquer des objets complexes sur un réseau. Nous verrons comment sérialiser un objet Commande pour l’envoyer d’une application cliente à un serveur de traitement dans un contexte d’e-commerce congolais.

VIII.3 Introduction au format JSON et son parsing

Omniprésent dans les applications web modernes, le format JSON (JavaScript Object Notation) est un standard de facto pour l’échange de données. Ce sous-chapitre se concentre sur la structure du JSON et sur les techniques et bibliothèques pour le “parser” (analyser) et le générer. L’étudiant apprendra à consommer des données d’une API REST, par exemple les données météorologiques pour une application agricole, ou les taux de change publiés par la Banque Centrale du Congo.

VIII.4 Principes des bases de données relationnelles et requêtes SQL simples

Pour une persistance structurée et à grande échelle, les bases de données sont incontournables. Cette section offre une introduction conceptuelle aux bases de données relationnelles (tables, clés primaires/étrangères). L’étudiant s’initiera au langage SQL avec des requêtes simples (SELECT, INSERT, UPDATE, DELETE) pour interagir avec une base de données, posant les fondations pour la création d’applications robustes gérant de grands volumes de données clients, produits ou transactions.

Chapitre IX. Interfaces graphiques (GUI) et programmation événementielle

IX.1 Paradigme de la programmation événementielle

Contrairement aux programmes en console, les applications graphiques ne suivent pas un flux séquentiel mais réagissent à des événements externes (clic de souris, frappe au clavier). Ce point introduit le paradigme événementiel : la boucle d’événements, les sources d’événements et les écouteurs (listeners). L’étudiant comprendra la rupture conceptuelle nécessaire pour concevoir des interfaces utilisateur interactives et réactives, typiques des applications desktop modernes.

IX.2 Composants graphiques fondamentaux : fenêtres, boutons, champs de texte

La construction d’une interface graphique repose sur l’assemblage de composants visuels. Cette section présente les briques de base de toute GUI : fenêtres, boîtes de dialogue, labels, boutons, champs de saisie, cases à cocher. L’étudiant apprendra à instancier, positionner et configurer ces composants pour créer des formulaires de saisie simples, comme un écran de connexion pour une application de gestion d’une microfinance à Matadi.

IX.3 Gestionnaires de mise en page (Layout Managers)

Le positionnement manuel des composants est fastidieux et ne s’adapte pas aux différentes tailles d’écran. Les gestionnaires de mise en page (Layout Managers) résolvent ce problème en organisant automatiquement les composants selon des règles prédéfinies (grille, flux, etc.). La maîtrise de ces outils est indispensable pour créer des interfaces professionnelles et “responsives” qui s’affichent correctement sur les divers écrans utilisés en RDC.

IX.4 Liaison des événements aux actions du code (Event Handling)

Une interface graphique n’est utile que si les interactions de l’utilisateur déclenchent des actions. Ce sous-chapitre se concentre sur le “câblage” : comment associer un écouteur d’événement à un composant et implémenter la logique métier à exécuter. Par exemple, l’étudiant apprendra à coder l’action qui se déclenche lors d’un clic sur le bouton “Valider”, comme la récupération des données du formulaire, leur validation et leur envoi à une base de données.

Chapitre X. Introduction aux tests et à l’intégration continue

X.1 Importance et typologie des tests logiciels

Un code qui fonctionne n’est pas nécessairement un code correct. Ce point souligne l’importance critique des tests pour garantir la qualité et la non-régression des logiciels. Nous distinguons les différents niveaux de tests : tests unitaires, qui valident un petit morceau de code isolé ; tests d’intégration, qui vérifient l’interaction entre composants ; et tests de bout-en-bout (E2E), qui simulent un parcours utilisateur complet dans l’application.

X.2 Écriture de tests unitaires avec un framework dédié

La pratique du test unitaire est la pierre angulaire de l’ingénierie logicielle moderne. Ce sous-chapitre guide l’étudiant dans l’utilisation d’un framework de test (comme JUnit pour Java ou NUnit pour .NET) pour écrire des tests automatisés pour ses classes. L’étudiant apprendra à tester les cas nominaux, les cas limites et les cas d’erreur pour une fonction de calcul ou une méthode de validation, assurant ainsi la robustesse de chaque brique de son application.

X.3 Le cycle de développement TDD (Test-Driven Development)

Le TDD inverse le cycle de développement traditionnel : on écrit d’abord un test qui échoue, puis on écrit le code minimal pour que le test passe, et enfin on refactorise le code. Cette discipline, bien que contre-intuitive au début, conduit à une meilleure conception et à une couverture de test de 100%. Nous explorons ce cycle “Rouge-Vert-Refactor” pour développer une nouvelle fonctionnalité dans une application de gestion des ressources humaines en RDC.

X.4 Principes de l’intégration continue (CI)

L’intégration continue est une pratique qui consiste à fusionner fréquemment les modifications de code de tous les développeurs dans un dépôt central, où des constructions et des tests automatisés sont exécutés. Cette section introduit les concepts de base de la CI et ses bénéfices : détection rapide des erreurs d’intégration, amélioration de la collaboration et accélération des livraisons. C’est une compétence clé pour travailler dans des équipes de développement agiles, même pour les startups de Kinshasa.

Chapitre XI. Concurrence et parallélisme : une introduction

XI.1 Distinction entre concurrence et parallélisme

Bien que souvent confondus, concurrence et parallélisme sont deux concepts distincts.
La concurrence est la capacité de gérer plusieurs tâches en apparence simultanément. Pensez à un jongleur qui manipule plusieurs balles. À un instant précis, il ne touche qu’une seule balle, mais en alternant rapidement son attention entre elles, il donne l’illusion de toutes les gérer en même temps. En informatique, cela signifie qu’un programme est structuré en plusieurs flux de contrôle qui peuvent s’exécuter de manière entrelacée. Un système concurrent peut fonctionner sur un processeur à un seul cœur, où le système d’exploitation bascule très vite d’une tâche à l’autre.

Le parallélisme, quant à lui, est l’exécution effectivement simultanée de plusieurs tâches. Il ne s’agit plus d’une illusion, mais d’une réalité matérielle. Pour cela, il faut disposer de plusieurs unités de calcul, comme les multiples cœurs d’un processeur moderne. Si l’on reprend l’analogie du jongleur, le parallélisme équivaudrait à avoir plusieurs jongleurs manipulant chacun leurs propres balles côte à côte.

En somme, la concurrence est une question de conception et de structure d’un programme (comment décomposer un problème en tâches indépendantes), tandis que le parallélisme est une question d’exécution matérielle. Un programme concurrent peut être exécuté en parallèle pour gagner en vitesse si le matériel le permet, mais il peut aussi s’exécuter sur un seul cœur. Le but de la concurrence est de structurer une solution pour gérer la complexité, alors que le but du parallélisme est d’accélérer l’exécution.

PARTIE 3 : Éléments d’algorithmique et de programmation orientée objet

Chapitre XII. Déploiement et Maintenance d’Applications Orientées Objet

XII.1 Packaging et Distribution d’Applications

Face aux défis de la distribution logicielle en contexte congolais, ce point détaille les techniques de packaging d’une application. Il s’agit de transformer le code source compilé en un installateur exécutable (MSI, DEB) ou une archive portable, en gérant rigoureusement les dépendances. La maîtrise de ce processus est cruciale pour déployer des solutions de gestion fiables auprès des PME de Kinshasa ou des coopératives agricoles du Kivu, garantissant une installation sans friction et une adoption rapide par les utilisateurs finaux.

XII.2 Introduction aux Patrons de Conception (Design Patterns)

Une maîtrise des patrons de conception (Design Patterns) distingue le programmeur de l’architecte logiciel. Cette section analyse des patrons fondamentaux comme le Singleton, la Fabrique (Factory) ou l’Observateur. L’objectif est de structurer le code pour qu’il soit réutilisable, flexible et maintenable. L’application de ces modèles est démontrée dans le cadre de la conception d’un système de gestion de stock pour une entreprise minière du Katanga, optimisant la robustesse et l’évolutivité de la solution logicielle.

XII.3 Techniques d’Optimisation et de Profiling

Sous l’angle de la performance, une application lente est une application inutile. Ce volet enseigne l’art du profiling : l’identification scientifique des goulots d’étranglement (CPU, mémoire, I/O) dans le code. Les étudiants apprendront à utiliser des outils d’analyse pour mesurer l’efficacité des algorithmes et à refactoriser les sections critiques. Cette compétence est vitale pour développer des applications réactives sur des infrastructures matérielles contraintes, une réalité fréquente pour de nombreuses organisations en RDC.

XII.4 Intégration de Frameworks et Maintenance Évolutive

L’intégration de frameworks modernes comme .NET ou Spring constitue une stratégie d’accélération du développement. Ce sous-chapitre explore comment s’appuyer sur ces fondations robustes pour construire des applications complexes plus rapidement. Il aborde également les principes de la maintenance évolutive et corrective via des systèmes de contrôle de version comme Git. L’enjeu est de garantir la pérennité des applications développées pour le marché congolais, en permettant des mises à jour sécurisées et l’ajout de nouvelles fonctionnalités.

ANNEXES

A. Glossaire Technique et Lexique Bilingue (Français-Lingala/Swahili)

Cette annexe constitue un pont linguistique et conceptuel essentiel. Elle ne se contente pas de définir les termes techniques de l’algorithmique et de la POO (Classe, Objet, Héritage, Polymorphisme, etc.), mais propose leur équivalence ou leur explication la plus proche en Lingala et Swahili. L’objectif est de démythifier le jargon, de faciliter l’appropriation profonde des concepts par les étudiants et de permettre la création de documentation technique accessible aux acteurs économiques locaux non-initiés.

B. Guide de bonnes pratiques pour le développement en contexte RDC

Ce guide pragmatique adresse les défis spécifiques au déploiement d’applications en République Démocratique du Congo. Il fournit des stratégies techniques pour la conception d’applications robustes face aux coupures d’électricité et à une connectivité internet intermittente (modes hors-ligne, synchronisation différentielle). Il aborde également l’optimisation des performances pour du matériel informatique d’entrée de gamme et la conception d’interfaces utilisateur adaptées aux divers niveaux de littératie numérique.


Discussion (0)

Aucune intervention pour le moment. Soyez le premier à contribuer.

Votre intervention Annuler la réponse

Leave a Reply

Your email address will not be published. Required fields are marked *