39 votes

Meilleures pratiques orientées objet - Héritage v Composition v Interfaces

Je veux poser une question sur la façon dont vous aborderiez un simple problème de conception orientée objet. J'ai quelques idées personnelles sur la meilleure façon d'aborder ce scénario, mais je serais intéressé par les opinions de la communauté Stack Overflow. Les liens vers des articles en ligne pertinents sont également appréciés. J'utilise C#, mais la question n'est pas spécifique au langage.

Supposons que j'écrive une application de vidéothèque dont la base de données comporte un fichier de type Person table, avec PersonId , Name , DateOfBirth et Address champs. Il dispose également d'un Staff qui contient un lien vers une PersonId et un Customer qui renvoie également à PersonId .

Une approche orientée objet simple consisterait à dire qu'une Customer "est un" Person et donc de créer des classes un peu comme ceci :

class Person {
    public int PersonId { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}

class Customer : Person {
    public int CustomerId { get; set; }
    public DateTime JoinedDate { get; set; }
}

class Staff : Person {
    public int StaffId { get; set; }
    public string JobTitle { get; set; }
}

Maintenant, nous pouvons écrire une fonction dire pour envoyer des emails à tous les clients :

static void SendEmailToCustomers(IEnumerable<Person> everyone) { 
    foreach(Person p in everyone)
        if(p is Customer)
            SendEmail(p);
}

Ce système fonctionne bien jusqu'à ce que nous ayons quelqu'un qui soit à la fois un client et un membre du personnel. En supposant que nous ne voulons pas vraiment que notre everyone liste d'avoir la même personne deux fois, une fois en tant que Customer et une fois en tant que Staff faisons-nous un choix arbitraire entre.. :

class StaffCustomer : Customer { ...

et

class StaffCustomer : Staff { ...

De toute évidence, seul le premier de ces deux cas n'enfreindrait pas les règles de l'UE. SendEmailToCustomers fonction.

Alors, que feriez-vous ?

  • Faites le Person ont des références facultatives à une classe StaffDetails et CustomerDetails classe ?
  • Créer une nouvelle classe qui contient un Person plus optionnel StaffDetails et CustomerDetails ?
  • Faire de chaque chose une interface (par exemple IPerson , IStaff , ICustomer ) et créer trois classes qui implémentent les interfaces appropriées ?
  • Adopter une autre approche complètement différente ?

1voto

Bogdan Points 11

Voici d'autres conseils : Dans la catégorie "ne pensez même pas à faire ça", voici quelques mauvais exemples de code rencontrés :

La méthode Finder renvoie un objet

Problème : En fonction du nombre d'occurrences trouvées, la méthode finder renvoie un nombre représentant le nombre d'occurrences - ou ! Si une seule occurrence est trouvée, elle renvoie l'objet réel.

Ne faites pas ça ! C'est l'une des pires pratiques de codage. Elle introduit une ambiguïté et désordonne le code de telle sorte que lorsqu'un autre développeur entrera en jeu, il vous détestera pour avoir fait cela.

Solution : S'il y a un besoin pour ces 2 fonctionnalités : compter et récupérer une instance, créez 2 méthodes, une qui retourne le compte et une qui retourne l'instance, mais jamais une seule méthode qui fait les deux.

Problème : Une mauvaise pratique dérivée est lorsqu'une méthode de recherche renvoie soit une seule occurrence trouvée, soit un tableau d'occurrences s'il y en a plusieurs. Ce style de programmation paresseux est souvent utilisé par les programmeurs qui font le précédent en général.

Solution : Dans ce cas, je retournerais un tableau de longueur 1(un) si une seule occurrence est trouvée et un tableau de longueur >1 si plusieurs occurrences sont trouvées. De plus, si je ne trouve aucune occurrence, je renvoie null ou un tableau de longueur 0, selon l'application.

Programmer en fonction d'une interface et utiliser des types de retour covariants

Problème : Programmation en fonction d'une interface et utilisation de types de retour covariants et du casting dans le code d'appel.

Solution : Utilisez plutôt le même supertype défini dans l'interface pour définir la variable qui doit pointer vers la valeur retournée. Cela permet de conserver l'approche de la programmation par interface et de garder votre code propre.

Les classes de plus de 1000 lignes représentent un danger potentiel. Les méthodes de plus de 100 lignes représentent également un danger potentiel !

Problème : Certains développeurs mettent trop de fonctionnalités dans une classe/méthode, étant trop paresseux pour casser la fonctionnalité - cela conduit à une faible cohésion et peut-être à un couplage élevé - l'inverse d'un principe très important dans la POO ! Solution : Évitez d'utiliser trop de classes internes/enchevêtrées - ces classes doivent être utilisées UNIQUEMENT en fonction des besoins, vous ne devez pas en faire une habitude ! Leur utilisation pourrait conduire à d'autres problèmes comme la limitation de l'héritage. Attention aux doublons de code ! Le même code ou un code trop similaire pourrait déjà exister dans l'implémentation d'un supertype ou peut-être dans une autre classe. S'il se trouve dans une autre classe qui n'est pas une supertype, vous avez également violé la règle de cohésion. Faites attention aux méthodes statiques - peut-être avez-vous besoin d'une classe utilitaire à ajouter !
Plus à : http://centraladvisor.com/it/oop-what-are-the-best-practices-in-oop

-1voto

jeremy Points 1

Vous ne voulez probablement pas utiliser l'héritage pour cela. Essayez plutôt ceci :

class Person {
    public int PersonId { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}

class Customer{
    public Person PersonInfo;
    public int CustomerId { get; set; }
    public DateTime JoinedDate { get; set; }
}

class Staff {
    public Person PersonInfo;
    public int StaffId { get; set; }
    public string JobTitle { get; set; }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X