Disons que j'ai une interface:
public interface IFeature
{
Task execFeature();
}
et deux implémentations:
public class FirstFeature : IFeature
{
private IWebApi webApi;
public FirstFeature(IWebApi webApi)
{
this.webApi = webApi;
}
public async Task execFeature()
{
string response = await webApi.getClassName();
IResult result;
if(response==null)
result = new TextResult("Error accessing api - check internet connection/api address");
else
result = new TextResult("Hello dear user – the selected class name is " + response);
result.display();
}
}
public class SecondFeature : IFeature
{
private IWebApi webApi;
public SecondFeature(IWebApi webApi)
{
this.webApi = webApi;
}
public async Task execFeature()
{
List<string> classNames = new List<string>();
var classNameTasks = Enumerable.Range(1, 3).Select(i => webApi.getClassName()).ToArray();
classNames.AddRange((await Task.WhenAll(classNameTasks)));
IResult result;
if (classNames[0] == null)
result = new TextResult("Error accessing api - check internet connection/api address");
else
result = new TextResult("Hello dear user – we’ve selected three new class names for you, and they are " + classNames[0] + ", " + classNames[1] + ", and " + classNames[2]);
result.display();
}
}
Comme vous pouvez le voir, dans les deux implémentations, j'ai had pour faire la ligne result = new TextResult("Error accessing api - check internet connection/api address");
pour signaler l'erreur.
Quelle est la meilleure pratique en POO/bonne conception pour avoir un error_string
Constant auquel je peux accéder dans toutes mes implémentations?
tel qu'il est actuellement, le code est dupliqué.
Je ne pense pas qu'il existe une meilleure pratique. C'est juste une question de préférence.
Je stocke des constantes dans des classes statiques.
public static class Constants
{
public static class Messages
{
public const string Error = "Error accessing api...";
public const string Hello = "Hello ...";
}
}
var result = new TextResult(Constants.Messages.Error);
FYI: Certains développeurs préfèrent Enum.
Je fais généralement une distinction en fonction du public cible du message. En tant que tel, je les divise en deux catégories.
Quelle que soit la catégorie, j'évite d'écrire le même code plus d'une fois (par exemple, les chaînes de message).
Messages des développeurs
Les options de mise en œuvre sont multiples. Je reste généralement simple, en utilisant des champs dans une classe statique. Notez que vous pouvez avoir une classe de messages pour chaque type qui affichera des messages, ou vous pouvez avoir une classe de messages centrale dans laquelle vous regroupez plusieurs classes. Vous pourriez avoir des groupes de messages imbriqués. Vous pouvez également ajouter d'autres types de constantes à utiliser dans votre code ... Comme je l'ai mentionné, les options et les préférences abondent.
public static class FeatureMessages
{
#region Public Fields
public const string ApiAccessError =
@"Error accessing api - check internet connection/api address";
public const string SelectedClassFormatString =
@"Hello dear user – the selected class name is {0}";
#endregion
}
Messages utilisateur
Je recommanderais généralement d'utiliser un fichier de ressources (créé à partir des paramètres de votre projet). Vous voudrez peut-être fournir une sorte de wrapper si vous voulez rendre ce code plus testable.
Mettez cela dans une classe statique:
internal static class ErrorMessage
{
public const string NoAccess = "Error accessing api - check internet connection/api address";
}
Et vous pouvez faire référence à cela en utilisant:
result = new TextResult(ErrorMessage.NoAccess);
Ou, vous pouvez utiliser un fichier de ressources.
Non pas que je ne sois pas d'accord avec la réponse de @ Win, je pense que placer les constantes Error et Hello qui sont logiquement liées à IFeature dans une classe statique non liée pour éviter la duplication pourrait ne pas être une approche appropriée. Si l'objectif est d'éviter les doublons, je voudrais y parvenir de la manière suivante:
public abstract class Feature:IFeature
{
public static readonly string Error = "Error accessing api...";
public static readonly string Hello = "Hello ...{0}";
protected IWebApi webApi;
protected Feature(IWebApi webApi)
{
this.webApi = webApi;
}
public async Task execFeature()
{
var o = _execFeature();
IResult result;
if(o==null)
result = new TextResult(Error);
else
result = new TextResult( string.Format(Hello, o);
result.display();
}
protected abstract object _execFeature();
}
Alors maintenant, j'ai atteint non seulement une minimisation optimale de la duplication de code, placez Error et Hello là où ils appartiennent logiquement. Les première et deuxième classes d'entités peuvent désormais hériter de la classe d'entités:
public class FirstFeature:Feature
{
public FirstFeature(IWebApi webApi):base(webApi){}
protected override object _execFeature ()
{
//your code for first Feature
//return response if no error else return null
}
}
public class SecondFeature:Feature
{
public SecondFeature(IWebApi webApi):base(webApi){}
protected override object _execFeature ()
{
//your code for second Feature
//return class name[0] if no error else return null
}
}
Voilà donc ce que serait mon design.