Dans cette série d'articles de blog , Eric Lippert décrit un problème de conception orientée objet utilisant des assistants et des guerriers comme exemples, où:
abstract class Weapon { }
sealed class Staff : Weapon { }
sealed class Sword : Weapon { }
abstract class Player
{
public Weapon Weapon { get; set; }
}
sealed class Wizard : Player { }
sealed class Warrior : Player { }
puis ajoute quelques règles:
- Un guerrier ne peut utiliser qu'une épée.
- Un assistant ne peut utiliser qu'un bâton.
Il continue ensuite à démontrer les problèmes que vous rencontrez si vous essayez d'appliquer ces règles en utilisant le système de type C # (par exemple, rendre la Wizard
classe responsable de s'assurer qu'un assistant ne peut utiliser qu'un bâton). Vous violez le principe de substitution Liskov, vous risquez des exceptions d'exécution ou vous vous retrouvez avec du code difficile à étendre.
La solution qu'il propose est qu'aucune validation n'est effectuée par la classe Player. Il est uniquement utilisé pour suivre l'état. Ensuite, au lieu de donner une arme à un joueur:
player.Weapon = new Sword();
l'état est modifié par Command
s et selon Rule
s:
... nous créons un
Command
objet appeléWield
qui prend deux objets d'état de jeu, aPlayer
et aWeapon
. Lorsque l'utilisateur envoie une commande au système «cet assistant doit manier cette épée», cette commande est alors évaluée dans le contexte d'un ensemble deRule
s, qui produit une séquence deEffect
s. Nous en avons unRule
qui dit que lorsqu'un joueur tente de manier une arme, l'effet est que l'arme existante, s'il y en a une, est lâchée et que la nouvelle arme devient l'arme du joueur. Nous avons une autre règle qui renforce la première règle, qui dit que les effets de la première règle ne s'appliquent pas lorsqu'un sorcier essaie de brandir une épée.
J'aime cette idée en principe, mais je me demande comment elle pourrait être utilisée dans la pratique.
Rien ne semble empêcher un développeur de contourner le Commands
et Rule
s en plaçant simplement le Weapon
sur a Player
. La Weapon
propriété doit être accessible par la Wield
commande, elle ne peut donc pas être créée private set
.
Alors, qu'est - ce qui empêche un développeur de faire cela? Doivent-ils simplement se rappeler de ne pas le faire?