Créa-blog

Ressources pour développeur web

La relation entre les classes et bonnes pratiques en POO

Accueil PHP 8 La relation entre les classes et bonnes pratiques en POO

En programmation orientée objet en PHP, la relation entre les classes leur permet d’interagir entre elles à travers des relations telles que l’association, l’agrégation et la composition.

La POO repose sur trois principaux concepts : les classes, les objets et l’encapsulation.

  • Une classe est un modèle qui définit les propriétés et les comportements des objets.
  • Un objet est une instance d’une classe, avec ses propres valeurs pour ses propriétés.
  • L’encapsulation est le principe de cacher les détails d’implémentation d’une classe et de n’exposer que les fonctionnalités nécessaires à l’extérieur.

Conception de Classes

La conception de classes consiste à identifier les entités principales de votre application et à les modéliser sous forme de classes. Chaque classe devrait avoir une seule responsabilité et suivre les principes SOLID pour garantir un code maintenable et évolutif.

Les principes SOLID

Les principes SOLID sont un ensemble de cinq principes de conception fondamentaux qui ont été formulés pour guider les développeurs dans la création de systèmes plus évolutifs, maintenables et flexibles. Ces principes ont été popularisés dans les années 2000. Voici une explication de chaque principe :

  • S – Single Responsibility Principle (Principe de Responsabilité Unique)
    Ce principe stipule qu’une classe ne devrait avoir qu’une seule raison de changer. En d’autres termes, une classe devrait avoir une seule responsabilité ou fonction, et toute modification à cette responsabilité devrait entraîner une modification de la classe. Cela permet de rendre les classes plus cohérentes, plus faciles à comprendre et à maintenir.
  • O – Open/Closed Principle (Principe d’Ouverture/Fermeture)
    Ce principe stipule qu’une classe devrait être ouverte à l’extension mais fermée à la modification. En d’autres termes, vous devriez pouvoir étendre le comportement d’une classe sans la modifier directement. Cela favorise la réutilisabilité du code et permet d’éviter les effets de bord lors de la modification du code existant.
  • L – Liskov Substitution Principle (Principe de Substitution de Liskov)
    Ce principe stipule qu’un objet de sous-classe doit pouvoir être utilisé en remplacement d’un objet de sa super-classe sans que cela ne modifie le comportement du programme. En d’autres termes, les objets dérivés doivent être substituables à leurs objets de base sans causer de bugs ou d’effets secondaires inattendus. Cela garantit que le polymorphisme fonctionne correctement dans votre application.
  • I – Interface Segregation Principle (Principe de Ségrégation d’Interface)
    Ce principe stipule qu’aucun client ne doit être forcé d’implémenter une interface qu’il n’utilise pas. En d’autres termes, une interface ne devrait pas être surchargée avec des méthodes dont les classes implémentantes n’ont pas besoin. Au lieu de cela, divisez les interfaces en interfaces plus petites et plus spécifiques afin que les classes clientes puissent implémenter uniquement ce dont elles ont besoin.
  • D – Dependency Inversion Principle (Principe d’Inversion de Dépendance)
    Ce principe stipule que les modules de haut niveau ne doivent pas dépendre des modules de bas niveau, mais plutôt des abstractions. En d’autres termes, les détails d’implémentation ne doivent pas être exposés au niveau supérieur. Au lieu de cela, les classes de haut niveau doivent dépendre d’interfaces ou d’abstractions, ce qui permet une plus grande flexibilité et un découplage plus fort entre les différentes parties de votre système.

Relation entre les classes

Dans cet exemple, la classe Utilisateur représente un utilisateur avec des propriétés telles que le nom et l’email. Les méthodes getNom() et getEmail() permettent d’accéder à ces propriétés de manière encapsulée.

class Utilisateur {
    private $nom;
    private $email;
    
    public function __construct($nom, $email) {
        $this->nom = $nom;
        $this->email = $email;
    }
    
    public function getNom() {
        return $this->nom;
    }
    
    public function getEmail() {
        return $this->email;
    }
}

Relation entre les classes

Les classes peuvent interagir les unes avec les autres à travers des relations telles que l’association, l’agrégation et la composition :

  • L’association est une relation faible entre deux classes, où une classe utilise l’autre de manière ponctuelle.
  • L’agrégation est une relation plus forte où une classe est composée d’autres classes qui peuvent exister de manière indépendante.
  • La composition est une relation encore plus forte où une classe est composée d’autres classes qui ne peuvent pas exister sans elle.

Relation d’association

Dans ce cas, la classe SalleDeDiscussion est associée à la classe Utilisateur. La relation d’association représente une relation entre deux classes où un objet de l’une peut utiliser ou interagir avec l’objet de l’autre. Dans cet exemple, la salle de discussion peut ajouter un utilisateur, mais aucun des deux objets ne possède ou ne contrôle l’autre.

class Utilisateur {
    public function envoyerMessage($message) {
        echo "Message envoyé : $message\n";
    }
}

class SalleDeDiscussion {
    public function ajouterUtilisateur(Utilisateur $utilisateur) {
        echo "Utilisateur ajouté à la salle de discussion\n";
    }
}

// Utilisation
$utilisateur = new Utilisateur();
$salleDeDiscussion = new SalleDeDiscussion();
$salleDeDiscussion->ajouterUtilisateur($utilisateur);

Relation d’agrégation

L’agrégation est une relation entre deux classes où une classe (appelée la classe agrégatrice) contient une référence à une autre classe (appelée la classe agrégée). La classe agrégatrice est responsable de la création et de la gestion de l’objet agrégé. Voici un exemple de code illustrant une relation d’agrégation en PHP :

Supposons que nous ayons deux classes : Utilisateur et Adresse. Un utilisateur peut avoir une adresse, mais cette adresse peut également exister indépendamment de l’utilisateur.

class Adresse {
    private $rue;
    private $ville;
    private $codePostal;

    public function __construct($rue, $ville, $codePostal) {
        $this->rue = $rue;
        $this->ville = $ville;
        $this->codePostal = $codePostal;
    }

    public function getAdresse() {
        return $this->rue . ', ' . $this->ville . ', ' . $this->codePostal;
    }
}

class Utilisateur {
    private $nom;
    private $adresse; // Référence vers l'objet Adresse

    public function __construct($nom, Adresse $adresse) {
        $this->nom = $nom;
        $this->adresse = $adresse;
    }

    public function getNom() {
        return $this->nom;
    }

    public function getAdresse() {
        return $this->adresse->getAdresse();
    }
}

// Création d'une adresse
$adresse = new Adresse('123 rue de la Ville', 'Ville', '12345');

// Création d'un utilisateur avec l'adresse
$utilisateur = new Utilisateur('John Doe', $adresse);

// Affichage des informations sur l'utilisateur et son adresse
echo "Nom de l'utilisateur : " . $utilisateur->getNom() . "\n";
echo "Adresse de l'utilisateur : " . $utilisateur->getAdresse() . "\n";

Dans cet exemple, la classe Utilisateur agrège la classe Adresse. Chaque utilisateur a une adresse associée, mais cette adresse peut exister indépendamment de l’utilisateur. Lorsque nous créons un utilisateur, nous passons une instance de la classe Adresse à son constructeur. Ensuite, nous pouvons accéder à l’adresse de l’utilisateur à l’aide de la méthode getAdresse().

Relation de composition

Dans cet exemple, la classe Facture est composée d’un objet de la classe Client. Il existe une relation de composition entre les deux classes, car une facture ne peut pas exister sans un client associé.

class Facture {
    private $client;
    
    public function __construct(Client $client) {
        $this->client = $client;
    }
}

class Client {
    private $nom;
    
    public function __construct($nom) {
        $this->nom = $nom;
    }
}