- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在构建一个从第三方检索并提交给第三方的服务。第三方提供了一个复杂的数据模型,其中包括三种不同的状态类型,它们都是带有模糊数字系列的整数。下面提供了一个示例(键:值):
HandlerStatus CustomerStatus ArchiveStatus--- --- ---activeUnallocated:40 draftOpen:0 openOpen:0 activeAllocated:26 submitted:2 closed:1activePromoted:102 approved:100Declined:2 declined:1... ...
只有有限数量的组合,每个组合都有一个期限(提交、委托(delegate)给另一个用户、等待确认等)。例如:
Combination called "Submitted":HandlerStatus has to be "activeUnallocated" (40)CustomerStatus has to be "submitted" (2)ArchiveStatus has to be "openOpen" (0)
我们可以预期会添加其他值,并且用户友好的名称可能会随着时间而改变。
此外,有些操作(如提交和委派给其他用户)不需要用户选择新值,这意味着服务需要知道在这些操作发生时必须设置的一组组合。
我想到了三种不同的解决方案,各有利弊。
优点:
缺点:
优点:
缺点:
优点:
缺点:
我已经尝试研究最佳实践和模式,以查看哪种解决方案最适合可维护性和良好的代码设计,但我没有取得任何进展(与此同时,我在开发过程中严重依赖魔术字符串和数字).
最佳答案
首先也是最重要的:你在避免魔数(Magic Number)和字符串方面是正确的。
一个经验法则是它是一个不会(经常)改变的整数,那么枚举是好的。如果它是一个不经常更改的字符串,那么其中包含字符串的静态(共享)类是好的。在这些情况下,您的目标是集中定义。这为您提供了几个优势,例如避免拼写错误(在字符串中),使代码更具可读性(使用枚举名称而不是数字)并且您可以跟踪使用(查找用法)。请注意,您可能不想使用 const关键字,除非您的值(value)观是一成不变的,永远不会改变。
对于经常变化的值,您需要考虑程序逻辑来处理这些值。没有人硬编码客户姓名和地址(希望如此),因此如果您的状态经常更改,您希望像处理任何其他数据一样处理它们。如果它们与程序逻辑相关联,那么您需要定义所需的程序逻辑并以某种方式链接状态。
对于更改频率较低的值,您可以选择硬编码(枚举/字符串)和从配置文件读取。硬编码显然需要重新编译,然后您应该考虑长期成本。今天需要你 5 分钟才能完成的事情,将来可能需要几天时间。 2 年后,分配更新其中一个值的任务的另一位开发人员可能会花费几天时间来设置正确的开发环境、编译和测试。看到从文件中读取值是多么容易,我的建议通常是使用配置文件。
对于您的特定问题,您似乎需要一个转换表。您的应用程序有特定的任务要执行。答案似乎使应用程序通用并将翻译放在文件中。您希望在文件(或 sql 表)中同时保留对状态更新的约束(什么会将什么状态转换为什么)和友好显示(对于用户)。简而言之,使应用程序无法了解状态字段经历的转换。
不要担心文件 IO。实现缓存很容易。
private static TranslationObject _translationObject = null;
public static TranslationObject GetTranslationObject() {
if (_translationObject == null)
lock (_translationObject)
_translationObject = JsonConvert.DeserializeObject<TranslationObject>(File.ReadAllTextt("TranslationTable.json"));
return _translationObject;
}
即使在网络应用程序中,该应用程序也会存活一段时间,因此这会在请求之间缓存文件。无论如何,操作系统应该有足够的内存来为几千字节的数据缓存磁盘 IO。
为了说明多种实现方法中的一种,我添加了一个示例,其中将结构与字典结合使用,以便在友好状态和其他状态组合之间进行快速双向查找。我不确定这是否正是您所要求的,但希望它能有所帮助。
void Main()
{
// Get translation
var translationObject = GetTranslationObject();
// Find friendly status based on combo
var friendly1 = translationObject.ComboStatusToFriendlyStatus[new StatusCombo(0, 30, 5)];
// Find combo based on friendly status
var combo1 = translationObject.FriendlyStatusToComboStatus[0];
}
public struct StatusCombo
{
// Please note that fields are readonly for immutability.
// This is particularly important since the GetHashCode() value is used in dictionaries.
// Note that status fields can also be strings (because we use .GetHashCode() in GetHashCode()).
public readonly int Status1;
public readonly int Status2;
public readonly int Status3;
[JsonConstructor]
public StatusCombo(int status1, int status2, int status3)
{
Status1 = status1;
Status2 = status2;
Status3 = status3;
}
public override int GetHashCode()
{
unchecked
{
int hashCode = Status1.GetHashCode();
hashCode = (hashCode * 397) ^ Status2.GetHashCode();
hashCode = (hashCode * 397) ^ Status3.GetHashCode();
// ... Repeat for every extra statuscode you add
return hashCode;
}
}
}
public class TranslationObject
{
public Dictionary<int, string> Status1Mapping;
public Dictionary<int, string> Status2Mapping;
public Dictionary<int, string> Status3Mapping;
public Dictionary<int, string> FriendlyStatus;
public Dictionary<int, StatusCombo> FriendlyStatusToComboStatus;
[JsonIgnore]
public Dictionary<StatusCombo, int> ComboStatusToFriendlyStatus;
}
private static TranslationObject _translationObject = null;
public static TranslationObject GetTranslationObject()
{
if (_translationObject == null)
lock ("Reading _translationObject")
{
_translationObject = JsonConvert.DeserializeObject<TranslationObject>(File.ReadAllText(@"TranslationTables.json"));
// Populate reverse lookup
_translationObject.ComboStatusToFriendlyStatus=new Dictionary<UserQuery.StatusCombo, int>();
foreach (var t in _translationObject.FriendlyStatusToComboStatus)
_translationObject.ComboStatusToFriendlyStatus.Add(t.Value, t.Key);
}
return _translationObject;
}
示例 JSON 文件:
{ "Status1Mapping": { "0": "Status1_0", "10": "Status1_1" }, "Status2Mapping": { "30": "Status2_0", "55": "Status2_1" }, "Status3Mapping": { "5": "Status3_0", "2": "Status3_1" }, "FriendlyStatus": { "0": "Submitted", "1": "Received" }, "FriendlyStatusToComboStatus": { "0": { "Status1": 10, "Status2": 55, "Status3": 2 }, "1": { "Status1": 0, "Status2": 30, "Status3": 5 } }}
And the code I used to populate the sample JSON:
var tro = new TranslationObject();
tro.Status1Mapping = new Dictionary<int, string>();
tro.Status2Mapping = new Dictionary<int, string>();
tro.Status3Mapping = new Dictionary<int, string>();
tro.Status1Mapping.Add(0, "Status1_0");
tro.Status1Mapping.Add(10, "Status1_1");
tro.Status2Mapping.Add(30, "Status2_0");
tro.Status2Mapping.Add(55, "Status2_1");
tro.Status3Mapping.Add(5, "Status3_0");
tro.Status3Mapping.Add(2, "Status3_1");
tro.FriendlyStatus = new Dictionary<int, string>();
tro.FriendlyStatus.Add(0, "Submitted");
tro.FriendlyStatus.Add(1, "Received");
tro.FriendlyStatusToComboStatus = new Dictionary<int, UserQuery.StatusCombo>();
tro.FriendlyStatusToComboStatus.Add(0, new StatusCombo(10, 55, 2));
tro.FriendlyStatusToComboStatus.Add(1, new StatusCombo(0, 30, 5));
File.WriteAllText(@"TranslationTables.json", JsonConvert.SerializeObject(tro));
关于c# - 防止魔数(Magic Number)和字符串的设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34471441/
谷歌搜索后,我发现可以使用魔数(Magic Number)来识别文件的内容类型。 在我的程序中,我想在服务器端验证文件内容类型。 我的客户端代码: function readF
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 6年前关闭。 Improve this questi
我在 Sonar 上收到此警告,认为这是违规行为。我需要适当的解决方案来从声纳中删除此警告。 我的代码是这样的: void method(){ try { int x; x=5; } ca
Cardano CLI 中有很多教程使用 --testnet-magic 3或 --testnet-magic 4在读取地址中的值、类型转换原生代币等过程中。但是他们都没有详细解释魔数(Magic N
我正在尝试编译“su” super 用户实用程序的修改版本,所以我在 git 上访问了 android5.0 源代码,并获得了“su.c”文件。 我的实际设备/硬件是乐视 x500 手机运行: And
我正在尝试编辑一些使用 python-magic 的代码,但出现导入错误:没有名为 magic 的模块。在我浏览互联网并找到有关使用我所做的 pip 安装 python-magic 的建议之前。我使用
您好,我正在尝试运行 python manage.py runserver 命令,但收到此错误消息 File "C:\Users\adrie\Anaconda3\lib\sre_compile.py"
我有这样一个函数: float_as_thousands_str_with_precision(value, precision) 如果我这样使用它: float_as_thousands_str_w
我有一个可以改变颜色的渐变,我希望其中的文本始终可见。 如果有任何开箱即用的资源,我宁愿动态地进行;我想要一个可以取消颜色的“魔笔”。 有什么实验吗? 最佳答案 Joel 对于如何对齐渐变画笔给出了很
Eclipse 生成的主细节流程在扩展 ListFragment 的类中有一些回调魔法 - 我说魔法是因为当你是 Android 和 Java 菜鸟时,它看起来就像是同时: ) 鉴于下面的代码,有人可
嗯,不完全是这样,但这里有一个例子。谁能解释一下B和C的区别?使用魔术函数动态设置值而不是简单地在属性定义中设置值如何更快? 这是一些代码: [root@vm-202-167-238-17 ~]# c
特地查看了下手册,关于php magic quotes,常见的几个设置如下,magic_quotes_gpc,magic_quotes_sybase,magic_quote_runtim
考虑这个类的安排 - 特别是魔术函数 __invoke: class Barman { public function __construct() { // .. .cons
是否可以在 Databricks 中导出“魔术 SQL”命令单元的输出? 我喜欢这样一个事实,即不必转义 SQL 命令,并且可以轻松地对其进行格式化。但是,我似乎无法在其他单元格中使用输出。我想要做的
我有来自 UploadedFile 按钮的文件,我想使用魔数(Magic Number)打印扩展文件, 我的代码: UploadedFile file = (UploadedFile)valueCha
我正在从头开始设计二进制文件格式,我想在开头包含一些魔术字节,以便可以轻松识别。我该如何选择哪些字节?我不知道任何魔数(Magic Number)的中央注册表,所以这只是选择一些尚未由附近 UNIX
问题:在 SQL 脚本或存储过程中避免魔数(Magic Number)或硬编码值的其他策略是什么? 考虑一个存储过程,它的工作是根据记录的StatusID 检查/更新记录的值。或其他一些 FK 查找表
我正在尝试使用Javascript的CryptoJS加密消息,如下所示: const encrypted_payload = CryptoJS.AES.encrypt("Hello, world!",
我使用“非常神奇”的正则表达式搜索(即/\v 或 %s/\v),但我希望我可以设置一些选项,这样我就不必再在任何地方包含\v 了。有办法做到这一点吗? 最佳答案 不是直接使用,但是您始终可以使用映射:
在哪里可以找到 Scala 的“神奇”函数列表,例如 apply、unapply、update、+= 等? 我所说的魔法函数是指编译器的某些语法糖使用的函数,例如 o.update(x,y) o(x
我是一名优秀的程序员,十分优秀!