Il ne s'agit pas seulement de POLA, mais aussi d'empêcher un état invalide comme source possible de bogues.
Voyons comment nous pouvons fournir quelques contraintes à votre exemple sans fournir une implémentation concrète:
Première étape: ne laissez rien être appelé avant l'ouverture d'un fichier.
CreateDataFileInterface
+ OpenFile(filename : string) : DataFileInterface
DataFileInterface
+ SetHeaderString(header : string) : void
+ WriteDataLine(data : string) : void
+ SetTrailerString(trailer : string) : void
+ Close() : void
Maintenant, il devrait être évident qu'il CreateDataFileInterface.OpenFile
faut appeler pour récupérer une DataFileInterface
instance, où les données réelles peuvent être écrites.
Deuxième étape: assurez-vous que les en-têtes et les remorques sont toujours définis.
CreateDataFileInterface
+ OpenFile(filename : string, header: string, trailer : string) : DataFileInterface
DataFileInterface
+ WriteDataLine(data : string) : void
+ Close() : void
Vous devez maintenant fournir tous les paramètres requis à l'avance pour obtenir un DataFileInterface
nom de fichier, un en-tête et une bande-annonce. Si la chaîne de fin n'est pas disponible jusqu'à ce que toutes les lignes soient écrites, vous pouvez également déplacer ce paramètre vers Close()
(renommer éventuellement la méthode en WriteTrailerAndClose()
) afin que le fichier au moins ne puisse pas être terminé sans chaîne de fin.
Pour répondre au commentaire:
J'aime la séparation de l'interface. Mais je suis enclin à penser que votre suggestion concernant l'application (par exemple, WriteTrailerAndClose ()) frôle une violation de SRP. (C'est une chose avec laquelle j'ai eu du mal à plusieurs reprises, mais votre suggestion semble être un exemple possible.) Comment répondriez-vous?
Vrai. Je ne voulais pas me concentrer sur l'exemple plus que nécessaire pour faire valoir mon argument, mais c'est une bonne question. Dans ce cas, je pense que je l'appellerais Finalize(trailer)
et dirais que cela ne fait pas trop. L'écriture de la bande-annonce et la fermeture ne sont que de simples détails de mise en œuvre. Mais si vous n'êtes pas d'accord ou avez une situation similaire où c'est différent, voici une solution possible:
CreateDataFileInterface
+ OpenFile(filename : string, header : string) : IncompleteDataFileInterface
IncompleteDataFileInterface
+ WriteDataLine(data : string) : void
+ FinalizeWithTrailer(trailer : string) : CompleteDataFileInterface
CompleteDataFileInterface
+ Close()
Je ne le ferais pas réellement pour cet exemple, mais cela montre comment appliquer la technique en conséquence.
Soit dit en passant, j'ai supposé que les méthodes doivent en fait être appelées dans cet ordre, par exemple pour écrire séquentiellement de nombreuses lignes. Si ce n'est pas obligatoire, je préférerais toujours un constructeur, comme le suggère Ben Cottrel .