实现使用的常量字符串的最佳实践

时间:2016-05-04 18:02:47

标签: c# string oop design-patterns interface

说我有一个界面:

public interface IFeature
{
    Task execFeature();
}

和两个实现:

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();
    }
}

正如您所看到的,在这两个实现中,我 执行result = new TextResult("Error accessing api - check internet connection/api address");行来报告错误。

在我的所有实现中,我可以访问的常量error_string是OOP / Good Design中的最佳做法是什么?

现在的方式,代码重复。

7 个答案:

答案 0 :(得分:30)

我认为没有最好的做法。这只是一个偏好问题。

我将常量存储在静态类中。

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);

仅供参考: 有些开发者更喜欢Enum。

答案 1 :(得分:9)

我通常会根据消息的目标受众进行区分。因此,我将它们分为两类。
无论类别如何,我都避免多次编写相同的代码(例如消息字符串)。

开发者消息

  • 单元测试 中显示的消息,仅在 调试 期间显示的消息,或记录为超级详细信息的消息 诊断 文件
  • 开发者消息需要 无本地化 ,并且应使用开发人员的语言编写。
    例如,如果开发公司位于莫斯科,那么用俄语写开发者消息就有很强的争议。
    在实践中,很多开发人员选择英语。
  • 实施选项是多重的。我通常使用静态类中的字段来保持简单。请注意,您可以为每个将显示消息的类型设置一个消息类,或者您可以在其中设置一个中央消息类,您可以在其中对多个类进行分组。您可以拥有嵌套的邮件组。您还可以在代码中添加其他类型的常量......正如我所提到的,选项和首选项比比皆是。

    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
    }
    

用户消息

  • 向最终用户显示的消息。例如,在 用户警告上,在用户 GUI菜单 中安装 提示 消息框等
  • 这些消息 应该已本地化
  • 实现很简单,至少需要一个默认的语言资源文件。有很多资源可以告诉你如何做到这一点,你可以看到一个简单的解释here

答案 2 :(得分:4)

我通常建议使用资源文件(根据项目设置创建)。如果您想使这段代码更易于测试,您可能需要提供某种包装器。

答案 3 :(得分:3)

将它放在静态类中:

            string password = UM.GetUserName(ULV.LoginName);
            string hash = UM.GetUserPassword(ULV.Password);
            string hashit = HashPassword(ULV.Password);

          public string GetUserPassword(string enteredPassword)
    {
        using (DemoDBEntities db = new DemoDBEntities())
        {
            var hash = HashPassword(enteredPassword);
            var user = db.SYSUsers.Where(o => o.PasswordEncryptedText.Equals(hash));
            if (user.Any())
                return user.FirstOrDefault().PasswordEncryptedText;
            else
                return string.Empty;
        }
    }

您可以使用:

来引用它
internal static class ErrorMessage
{
    public const string NoAccess = "Error accessing api - check internet connection/api address";
}

或者,您可以使用资源文件。

答案 4 :(得分:2)

不是我不同意@Win的答案,我认为为了避免重复而将无关静态类中与IFeature逻辑相关的Error和Hello consts放在一起可能不合适。如果目标是避免重复,那么我想以下列方式实现它:

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();
}

所以现在我不仅实现了代码重复的最佳最小化,而且将Error和Hello放在逻辑上属于它们的位置。第一个和第二个Feature类现在可以从Feature类继承:

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
    }
}

这就是我的设计。

答案 5 :(得分:-4)

除了您的功能正在显示消息(我认为它不应该这样做)之外,如果您在代码中添加消息,则显然存在本地化问题。无论你在哪里以及如何访问它,你都不想重新编译以使用不同的语言。您可能甚至不想重新编译来修复一个愚蠢的拼写错误。

在您的代码中,使用错误代码。例如,这可以是枚举。然后在您的前端应用程序中,有一个翻译服务(.NET有一个非常好的功能,称为&#34;资源&#34;为此)。

通过这种方式,您可以为不同的前端提供不同的资源(例如一个用于法语。或者一个用于语言更容易的孩子。或者一个用于能够处理真实交易的技术人员。)

此外,您还可以拥有一个可以对代码作出反应的自动化前端,而不必解析错误消息,并在有人纠正拼写错误或找到更好的术语时抛出适合的东西。

答案 6 :(得分:-4)

这里有一些代码。

   namespace myNS
   {
       class MyClass
       {

           private readonly static string MyKey = "MyKey";

        //MyCode
       }
   }