Considérez deux classes Dog
et les Cat
deux conformes au Animal
protocole (en termes de langage de programmation Swift. Ce serait l'interface en Java / C #).
Nous avons un écran affichant une liste mixte de chiens et de chats. Il y a une Interactor
classe qui gère la logique dans les coulisses.
Maintenant, nous voulons présenter une alerte de confirmation à l'utilisateur lorsqu'il souhaite supprimer un chat. Cependant, les chiens doivent être supprimés immédiatement sans aucune alerte. La méthode avec des conditions ressemblerait à ceci:
func tryToDeleteModel(model: Animal) {
if let model = model as? Cat {
tellSceneToShowConfirmationAlert()
} else if let model = model as? Dog {
deleteModel(model: model)
}
}
Comment refactoriser ce code? Ça sent évidemment
la source
Dog
etCat
sont décrites comme des classes, toutAnimal
est un protocole qui est mis en œuvre par chacune de ces classes. Il y a donc un peu de décalage entre la question et votre réponse.Interactor
état maintenantCat
etDog
traitées, elle peut et doit être une propriété commune dansAnimal
. Faire autre chose, c'est demander un mal de tête de maintenance plus tard.Tell vs. Ask
L'approche conditionnelle que vous montrez que nous appellerions « demander ». C'est là que le client consommateur demande "quel genre êtes-vous?" et personnalise leur comportement et leur interaction avec les objets en conséquence.
Cela contraste avec l'alternative que nous appelons " dire ». En utilisant tell , vous poussez plus de travail dans les implémentations polymorphes, de sorte que le code client consommateur est plus simple, sans conditions et commun quelles que soient les implémentations possibles.
Puisque vous souhaitez utiliser une alerte de confirmation, vous pouvez en faire une capacité explicite de l'interface. Ainsi, vous pouvez avoir une méthode booléenne qui vérifie éventuellement avec l'utilisateur et renvoie la confirmation booléenne. Dans les classes qui ne veulent pas confirmer, elles remplacent simplement
return true;
. D'autres implémentations peuvent déterminer dynamiquement si elles souhaitent utiliser la confirmation.Le client consommateur utiliserait toujours la méthode de confirmation quelle que soit la sous-classe particulière avec laquelle il travaille, ce qui fait que l'interaction indique au lieu de demander .
(Une autre approche consisterait à pousser la confirmation dans la suppression, mais cela surprendrait les clients consommateurs qui s'attendent à ce qu'une opération de suppression réussisse.)
la source
Interactor
état maintenantDéterminer si une confirmation est nécessaire est la responsabilité de la
Cat
classe, alors permettez-lui d'exécuter cette action. Je ne connais pas Kotlin, donc j'exprimerai les choses en C #. Espérons que les idées soient ensuite transférables à Kotlin aussi.Ensuite, lors de la création d'une
Cat
instance, vous la fournissezTellSceneToShowConfirmationAlert
, qui devra être renvoyéetrue
si OK pour la supprimer:Et puis votre fonction devient:
la source
Cat
classe. Je dirais que c'est à cela qu'il appartient. Il ne parvient pas à décider comment cette confirmation est obtenue (qui est injectée) et il ne se supprime pas lui-même. Donc non, cela ne déplace pas la logique de suppression dans le modèle.TellSceneToShowConfirmationAlert
dans une instance deCat
. Dans des situations où ce n'est pas une chose facile (comme dans un système multicouche où cette fonctionnalité se situe à un niveau profond), alors cette approche ne serait pas bonne.Je conseillerais d'aller pour un modèle de visiteur. J'ai fait une petite implémentation en Java. Je ne connais pas Swift, mais vous pouvez l'adapter facilement.
Le visiteur
Votre modèle
Appeler le visiteur
Vous pouvez avoir autant d'implémentations d'AnimalVisitor que vous le souhaitez.
Exemple:
la source