Je me demande ce qui est mieux en termes de bonne conception OOP, de code propre, de flexibilité et d'éviter les odeurs de code à l'avenir. Situation d'image, où vous avez beaucoup d'objets très similaires que vous devez représenter en tant que classes. Ces classes sont sans aucune fonctionnalité spécifique, juste des classes de données et sont différentes uniquement par leur nom (et leur contexte) Exemple:
Class A
{
String name;
string description;
}
Class B
{
String name;
String count;
String description;
}
Class C
{
String name;
String count;
String description;
String imageUrl;
}
Class D
{
String name;
String count;
}
Class E
{
String name;
String count;
String imageUrl;
String age;
}
Serait-il préférable de les conserver dans des classes séparées, pour obtenir une "meilleure" lisibilité, mais avec de nombreuses répétitions de code, ou serait-il préférable d'utiliser l'héritage pour être plus SEC?
En utilisant l'héritage, vous vous retrouverez avec quelque chose comme ça, mais les noms de classe perdront leur signification contextuelle (à cause de is-a, not has-a):
Class A
{
String name;
String description;
}
Class B : A
{
String count;
}
Class C : B
{
String imageUrl;
}
Class D : C
{
String age;
}
Je sais que l'héritage n'est pas et ne devrait pas être utilisé pour la réutilisation du code, mais je ne vois pas d'autre moyen possible de réduire la répétition du code dans ce cas.
la source
Exactement. Regardez cela, hors contexte:
Quelles sont les propriétés d'un D? Vous souvenez-vous? Et si vous compliquez davantage la hiérarchie:
Et puis si, horreur après horreur, vous voulez ajouter un champ imageUrl à F mais pas E? Vous ne pouvez pas le dériver de C et E.
J'ai vu une situation réelle où de nombreux types de composants différents avaient tous un nom, un ID et une description. Mais ce n'était pas par la nature de leurs composants, c'était juste une coïncidence. Chacun avait un identifiant car ils étaient stockés dans une base de données. Le nom et la description devaient être affichés.
Les produits avaient également un ID, un nom et une description, pour des raisons similaires. Mais ce n'étaient pas des composants, ni des produits de composants. Vous ne verriez jamais les deux choses ensemble.
Mais, un développeur avait lu sur DRY et avait décidé de supprimer toute trace de duplication du code. Il a donc appelé tout un produit et a supprimé la nécessité de définir ces domaines. Ils étaient définis dans Product et tout ce qui avait besoin de ces champs pouvait dériver de Product.
Je ne peux pas le dire assez fort: ce n'est pas une bonne idée.
DRY ne consiste pas à supprimer le besoin de propriétés communes. Si un objet n'est pas un produit, ne l'appelez pas un produit. Si un produit N'EXIGE PAS une description, par la nature même de son caractère de produit, ne définissez pas la description comme une propriété du produit.
Il s'est avéré, finalement, que nous avions des composants sans descriptions. Nous avons donc commencé à avoir des descriptions nulles dans ces objets. Non annulable. Nul. Toujours. Pour tout produit de type X ... ou ultérieur Y ... et N.
Il s'agit d'une violation flagrante du principe de substitution de Liskov.
DRY consiste à ne jamais se mettre dans une position où vous pourriez corriger un bug à un endroit et oublier de le faire ailleurs. Cela ne va pas se produire car vous avez deux objets avec la même propriété. Jamais. Alors ne vous en faites pas.
Si le contexte des classes rend évident que vous devriez, ce qui sera très rare, alors et seulement alors, vous devriez considérer une classe parente commune. Mais, s'il s'agit de propriétés, réfléchissez à la raison pour laquelle vous n'utilisez pas d'interface à la place.
la source
L'hérédité est un moyen d'obtenir un comportement polymorphe. Si vos classes n'ont aucun comportement, l'héritage est inutile. Dans ce cas, je ne les considérerais même pas comme des objets / classes, mais plutôt comme des structures.
Si vous souhaitez pouvoir mettre différentes structures dans différentes parties de votre comportement, envisagez des interfaces avec des méthodes ou des propriétés get / set, comme IHasName, IHasAge, etc. Cela rendra la conception beaucoup plus propre et permettra une meilleure composition de celles-ci. genre de hiearchies.
la source
N'est-ce pas à cela que servent les interfaces? Classes sans rapport avec des fonctions différentes mais avec une propriété similaire.
la source
Votre question semble être encadrée dans le contexte d'un langage qui ne prend pas en charge l'héritage multiple mais ne le spécifie pas spécifiquement. Si vous travaillez avec un langage qui prend en charge l'héritage multiple, cela devient très facile à résoudre avec un seul niveau d'héritage.
Voici un exemple de la façon dont cela peut être résolu en utilisant l'héritage multiple.
la source