Vous n’êtes pas obligé de respecter strictement ces principes et il n’existe aucune sanction religieuse en cas de violation de ces principes. Mais vous devez considérer ces principes comme une sonnette d’alarme. Si l’un d’entre eux est violé, la sonnette d’alarme retentit.
(1) Toutes les données doivent être cachées dans la classe où elles se trouvent.
(2) Les utilisateurs d'une classe doivent s'appuyer sur l'interface partagée de la classe, mais une classe ne peut pas s'appuyer sur ses utilisateurs.
(3) Réduisez les messages dans le protocole de classe.
(4) Implémenter l'interface publique la plus élémentaire que toutes les classes comprennent [par exemple, les opérations de copie (copie approfondie et copie superficielle), le jugement d'égalité, le contenu de sortie correct, l'analyse à partir de la description ASCII, etc.].
(5) Ne placez pas les détails d'implémentation (tels que les fonctions privées qui placent du code partagé) dans l'interface publique de la classe. Si deux méthodes d'une classe ont un morceau de code commun, vous pouvez créer une fonction privée qui empêche ce code commun.
(6) Ne perturbez pas l'interface publique de la classe avec des éléments que les utilisateurs ne peuvent pas utiliser ou qui ne les intéressent pas.
(7) Il ne devrait y avoir aucun couplage entre les classes, ou uniquement des relations de couplage dérivées. Autrement dit, soit une classe n'a rien à voir avec une autre classe, soit elle utilise uniquement des opérations dans l'interface publique d'une autre classe.
(8) Une classe ne doit représenter qu’une seule abstraction clé. Toutes les classes du package doivent être fermées conjointement pour les modifications du même type de propriétés. Si un changement affecte un package, il affectera toutes les classes du package, mais n'aura aucun impact sur les autres packages
(9) Centraliser les données et les comportements associés. Les concepteurs doivent être conscients des objets qui obtiennent des données d'autres objets via des opérations telles que get. Ce type de comportement implique que ce principe empirique est violé.
(10) Mettez les informations non pertinentes dans une autre catégorie (c'est-à-dire le comportement consistant à ne pas communiquer entre eux). Créez des dépendances vers la stabilité.
(11) Assurez-vous que les concepts abstraits que vous modélisez sont des classes, pas seulement les rôles joués par les objets.
(12) Répartir les fonctions du système aussi uniformément que possible dans le sens horizontal, c'est-à-dire que selon la conception, les classes de niveau supérieur doivent partager le travail de manière uniforme.
(13) Ne créez pas de classes/objets omnipotents dans votre système. Soyez particulièrement prudent avec les classes dont les noms incluent Driver, Manager, System et Susystem. Planifiez une interface plutôt que d’implémenter une interface.
(14) Soyez prudent avec les classes qui définissent un grand nombre de méthodes d'accès dans l'interface publique. Le grand nombre de méthodes d’accès signifie que les données et comportements pertinents ne sont pas stockés de manière centralisée.
(15) Soyez prudent avec les cours qui contiennent trop de comportements qui ne communiquent pas entre eux. Une autre manifestation de ce problème est la création de nombreuses fonctions get et set dans l'interface publique des classes de votre application.
(16) Dans une application constituée d'un modèle orienté objet qui interagit avec l'interface utilisateur, le modèle ne devrait pas dépendre de l'interface, mais l'interface devrait dépendre du modèle.
(17) Modéliser autant que possible en fonction du monde réel (nous violons souvent ce principe afin de respecter le principe de distribution des fonctions du système, d'éviter le principe de classe polyvalent et de placer de manière centralisée les données et les comportements pertinents).
(18) Supprimez les classes inutiles de votre conception. En règle générale, nous rétrograderions cette classe en propriété.
(19) Supprimer les classes en dehors du système. La caractéristique des classes extérieures au système est que, en termes abstraits, elles envoient uniquement des messages au domaine système mais n'acceptent pas les messages provenant d'autres classes du domaine système.
(20) Ne transformez pas les opérations en classes. Interrogez toute classe dont le nom est un verbe ou dérivé d'un verbe, en particulier une classe avec une seule action significative. Déterminez si ce comportement significatif doit être déplacé vers une classe qui existe déjà ou qui n’a pas encore été découverte.
(21) Nous introduisons souvent des classes proxy lors de la création de modèles d'analyse d'applications. Lors de la phase de conception, nous constatons souvent que de nombreux agents sont inutiles et doivent être supprimés.
(22) Minimiser le nombre de collaborateurs d'une classe. Le nombre d’autres classes utilisées par une classe doit être réduit au minimum.
(23) Minimiser le nombre de messages transmis entre les classes et les collaborateurs.
(24) Minimiser la quantité de collaboration entre les classes et les collaborateurs, c'est-à-dire : réduire le nombre de messages différents transmis entre les classes et les collaborateurs.
(25) Minimiser la diffusion de la classe, c'est-à-dire réduire le produit du nombre de messages définis par la classe et du nombre de messages envoyés.
(26) Si une classe contient un objet d'une autre classe, la classe contenante doit envoyer un message à l'objet contenu. Autrement dit : une relation d’inclusion implique toujours une relation d’usage.
(27) La plupart des méthodes définies dans une classe devraient utiliser la plupart des données membres la plupart du temps.
(28) Le nombre d'objets contenus dans une classe ne doit pas dépasser la capacité de la mémoire à court terme du développeur. Ce nombre est souvent 6. Lorsqu'une classe contient plus de 6 données membres, vous pouvez diviser les données membres logiquement liées en un groupe, puis utiliser une nouvelle classe conteneur pour contenir ce groupe de membres.
(29) Laissez les fonctions du système être distribuées verticalement dans un système d'héritage étroit et profond.
(30) Lors de la mise en œuvre de contraintes sémantiques, il est préférable de les mettre en œuvre conformément aux définitions de classe. Cela conduit souvent à un débordement de classe, auquel cas les contraintes doivent être implémentées dans le comportement de la classe, généralement mais pas nécessairement dans le constructeur.
(31) Lors de l'implémentation de contraintes sémantiques dans le constructeur d'une classe, placez le test de contrainte dans le niveau d'inclusion le plus profond autorisé par le domaine du constructeur.
(32) Si les informations sémantiques sur lesquelles reposent les contraintes changent fréquemment, il est préférable de les placer dans un objet tiers centralisé.
(33) Si l'information sémantique sur laquelle reposent les contraintes change rarement, il est préférable de la répartir entre les classes impliquées dans les contraintes.
(34) Une classe doit savoir ce qu'elle contient, mais elle ne peut pas savoir qui le contient.
(35) Les objets qui partagent une portée littérale (c'est-à-dire qui sont contenus dans la même classe) ne doivent pas avoir de relation d'utilisation les uns avec les autres.
(36) L’héritage ne devrait être utilisé que pour modéliser les hiérarchies de spécialisation.
(37) Les classes dérivées doivent connaître les classes de base, et les classes de base ne doivent connaître aucune information sur leurs classes dérivées.
(38) Toutes les données de la classe de base doivent être privées, n'utilisez pas de données protégées. Les concepteurs de classe ne devraient jamais placer dans une interface publique des éléments dont les utilisateurs de la classe n'ont pas besoin.
(39) En théorie, la hiérarchie successorale devrait être plus profonde, plus elle est profonde, mieux c'est.
(40) En pratique, la profondeur de la hiérarchie successorale ne devrait pas dépasser la capacité de mémoire à court terme d’une personne moyenne. Une valeur de profondeur largement acceptée est 6.
(41) Toutes les classes abstraites doivent être des classes de base.
(42) Toutes les classes de base doivent être des classes abstraites.
(43) Placer les données, les comportements et/ou les points communs d'interface aussi haut que possible dans la hiérarchie d'héritage.
(44) Si deux classes ou plus partagent des données communes (mais aucun comportement commun), alors les données communes doivent être placées dans une classe incluse dans chaque classe partageant ces données.
(45) Si deux classes ou plus ont des données et un comportement communs (c'est-à-dire des méthodes), alors chacune de ces classes doit hériter d'une classe de base commune qui représente ces données et méthodes.
(46) Si deux classes ou plus partagent une interface commune (faisant référence à des messages et non à des méthodes), elles ne devraient alors hériter d'une classe de base commune que si elles doivent être utilisées de manière polymorphe.
(47) L'analyse au cas par cas de l'affichage des types d'objets est généralement erronée. Dans la plupart de ces cas, les concepteurs doivent utiliser le polymorphisme.
(48) L'analyse au cas par cas de l'affichage des valeurs d'attribut est souvent erronée. Les classes doivent être découplées dans une hiérarchie d'héritage, chaque valeur d'attribut étant transformée en classe dérivée.
(49) Ne modélisez pas la sémantique dynamique d'une classe à travers des relations d'héritage. Tenter de modéliser une sémantique dynamique avec des relations sémantiques statiques entraîne un changement de type au moment de l'exécution.
(50) Ne transformez pas les objets de classe en classes dérivées. Soyez prudent avec toute classe dérivée qui n'a qu'une seule instance.
(51) Si vous pensez que vous devez créer une nouvelle classe au moment de l'exécution, prenez du recul et réalisez que vous créez des objets. Maintenant, généralisons ces objets dans une classe.
(52) Il devrait être illégal d'utiliser une méthode vide (c'est-à-dire une méthode qui ne fait rien) dans une classe dérivée pour remplacer une méthode dans la classe de base.
(53) Ne pas confondre inclusion facultative et nécessité d’héritage. La modélisation de l'inclusion facultative comme héritage conduit à une prolifération de classes.
(54) Lors de la création de hiérarchies d'héritage, essayez de créer des cadres réutilisables plutôt que des composants réutilisables.
(55) Si vous utilisez l'héritage multiple dans votre conception, supposez que vous avez commis une erreur. Si vous n’avez pas commis d’erreur, vous devez essayer de le prouver.
(56) Chaque fois que l'héritage est utilisé dans la conception orientée objet, posez-vous deux questions : (1) La classe dérivée est-elle un type spécial de la chose dont elle hérite ? (2) La classe de base fait-elle partie de la classe dérivée ?
(57) Si vous trouvez un héritage multiple dans une conception orientée objet, assurez-vous qu'aucune classe de base n'est en réalité une classe dérivée d'une autre classe de base.
(58) Dans la conception orientée objet, si vous devez choisir entre l'inclusion et l'association, veuillez choisir l'inclusion.
(59) N'utilisez pas de données globales ou de fonctions globales pour la comptabilité des objets d'une classe. Des variables de classe ou des méthodes de classe doivent être utilisées.
(60) Les concepteurs orientés objet ne devraient pas laisser les principes de conception physique miner leurs conceptions logiques. Cependant, nous utilisons souvent des critères de conception physique pour prendre des décisions concernant la conception logique.
(61) Ne contournez pas l'interface publique pour modifier l'état de l'objet.