将一个用于许多方法的硬编码字符串重构为两个



我有一个类似于下面的情况。它是一个REST API helper类,具有针对不同API端点的方法,并为其提供头文件。其中一个标题,ChannelId,被硬编码为"Channel 1"。

从现在开始,应该可以有"频道2"代替。重构它的好策略是什么?我已经提供了我的建议,但不知何故,这感觉像是一种廉价的方法。因为我需要在很多方法中修改签名。

public class RestApiRequestHelper
{
public void MethodA()
{
var request = new RestRequest(RestRequest.GET);
AddHeaders(request);
//...
}
//... more similar methods using AddHeaders(request)
public void MethodZ()
{

var request = new RestRequest(RestRequest.GET);
AddHeaders(request);
//...
}
private void AddHeaders(RestRequest request)
{
request.AddHeader("ChannelId", "Channel 1");
//...
}
}

我的建议:

public class RestApiRequestHelper
{
public void MethodA(string channelId)
{
var request = new RestRequest(RestRequest.GET);
AddHeaders(request, channelId);
//...
}
//... more similar methods using AddHeaders(request)
public void MethodZ(string channelId)
{
var request = new RestRequest(RestRequest.GET);
AddHeaders(request, channelId);
//...
}
private void AddHeaders(RestRequest request, string channelId)
{
request.AddHeader("ChannelId", channelId);
//...
}
}

从API消费者的角度来看,新版本是一个突破性的变化,它真的很容易出错。

  • 突破性更改:消费者必须采用新的API,因为它不向后兼容。
  • 易出错:消费者现在可以用几乎任何东西调用这个API,比如:null,"ThisIsNotExistingChannelId","ThisIsAMisspelledChannelId",await LongRunningOperationToObtainChannelId()等。

的向后兼容性如果你不想引入破坏性的更改(这样你的客户端就可以使用API而不需要任何代码更改),那么你可以使用可选参数。

默认值

参数
public void MethodA(string channelId = "Channel 1")
{
var request = new RestRequest(RestRequest.GET);
AddHeaders(request, channelId);
//...
}

带回退值的参数

public void MethodA(string channelId = default)
{
var request = new RestRequest(RestRequest.GET);
AddHeaders(request, channelId ?? "Channel 1");
//...
}

参数限制如果你不允许任何类型的通道标识符,那么你也可以限制它。

运行时检查

private static readonly ImmutableArray<string>
ValidChannelIds = ImmutableArray.Create("Channel 1", "Channel 2");
public void MethodA(string channelId = default)
{
if(!ValidChannelIds.Contains(channelId))
throw new ArgumentOutOfRangeException(nameof(channelId), 
$"The provided channel is invalid. Valid ids are: '{string.Join(',', ValidChannelIds)}'");
...
}

编译时间和运行时检查

public enum Channels
{
[Description("Channel 1")]
Ch1 = 0,
[Description("Channel 2")]
Ch2 = 2,
}
public void MethodA(Channels channelId = Channels.Ch1)
{
if(!Enum.IsDefined(typeof(Channels), channelId))
throw new ArgumentOutOfRangeException(nameof(channelId), 
$"The provided channel is invalid. Valid ids: '{string.Join(',', Enum.GetNames(typeof(Channels)))}'");

var fieldInfo = typeof(Channels).GetField(channelId.ToString("G"));
var chId = fieldInfo.GetCustomAttribute<DescriptionAttribute>().Description;
...
}

需要Enum.IsDefined,因为您也可以这样调用方法:MethodA((Channels)3);和3不会有Description

相关内容

  • 没有找到相关文章

最新更新