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 Wizardclasse 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 Commands et selon Rules:
... nous créons un
Commandobjet appeléWieldqui prend deux objets d'état de jeu, aPlayeret 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 deRules, qui produit une séquence deEffects. Nous en avons unRulequi 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 Commandset Rules en plaçant simplement le Weaponsur a Player. La Weaponpropriété doit être accessible par la Wieldcommande, 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?