L'idée de base derrière la POO est que les données et le comportement (sur ces données) sont inséparables et qu'ils sont couplés à l'idée d'un objet d'une classe. Les objets ont des données et des méthodes qui fonctionnent avec ça (et d’autres données). Évidemment, selon les principes de la POO, les objets qui ne sont que des données (comme les structures C) sont considérés comme des anti-modèles.
Jusqu'ici tout va bien.
Le problème est que j'ai remarqué que mon code semble aller de plus en plus dans la direction de cet anti-pattern ces derniers temps. Il me semble que plus j'essaye de cacher des informations entre des classes et des conceptions faiblement couplées, plus mes classes deviennent un mélange de classes de données pures sans comportement et de tout comportement sans classes de données.
Je conçois généralement les classes de manière à minimiser leur connaissance de l'existence des autres classes et leur connaissance des interfaces des autres classes. J'applique cela de manière descendante, les classes de niveau inférieur ne connaissent pas les classes de niveau supérieur. Par exemple:
Supposons que vous ayez une API de jeu de cartes générale. Vous avez une classe Card
. Maintenant, cette Card
classe doit déterminer la visibilité pour les joueurs.
Une façon est d'avoir boolean isVisible(Player p)
sur la Card
classe.
Une autre est d'avoir boolean isVisible(Card c)
sur la Player
classe.
Je n'aime pas particulièrement la première approche, qui accorde des connaissances sur les Player
classes supérieures à une Card
classe inférieure .
Au lieu de cela, j'ai opté pour la troisième option où nous avons une Viewport
classe qui, à partir d' Player
une liste de cartes, détermine quelles cartes sont visibles.
Cependant, cette approche prive les classes Card
et les Player
classes d'une fonction membre possible. Une fois que vous faites cela pour d' autres choses que la visibilité des cartes, il vous reste Card
et les Player
classes qui contiennent uniquement des données que toutes les fonctionnalités sont mis en œuvre dans d' autres classes, qui sont pour la plupart des classes sans données, seulement des méthodes, comme le Viewport
ci - dessus.
Cela va clairement à l’encontre de l’idée principale de la programmation orientée objet.
Quelle est la bonne façon? Comment faire pour minimiser les interdépendances entre les classes et les connaissances et couplages supposés, sans pour autant aboutir à une conception bizarre où toutes les classes de bas niveau contiennent uniquement des données et les classes de haut niveau contiennent toutes les méthodes? Quelqu'un at-il une troisième solution ou perspective sur la conception de classe qui évite tout le problème?
PS Voici un autre exemple:
Supposons que vous ayez une classe DocumentId
immuable, qu’un seul BigDecimal id
membre et un getter pour ce membre. Maintenant, vous devez avoir une méthode quelque part, qui donne un DocumentId
retour Document
pour cet identifiant depuis une base de données.
Le faites vous:
- Ajoutez une
Document getDocument(SqlSession)
méthode à laDocumentId
classe, introduisant soudainement des connaissances sur votre persistance ("we're using a database and this query is used to retrieve document by id"
), l’API utilisée pour accéder à une base de données, etc. De plus, cette classe nécessite maintenant la persistance du fichier JAR pour la compilation. - Ajoutez une autre classe avec la méthode
Document getDocument(DocumentId id)
, en laissant laDocumentId
classe morte, sans comportement, comme une classe semblable à la structure.