- 主题:enum or int?
最近在搞一个项目,需要和不同的模块接口,这些模块是管理不同的硬件的,比如设备的性能等。那么就需要调节的频率电压什么的。我就想写一个程序,读入一个配置文件,是json格式,里面写上控制的数据即可。这样,可以控制不同的设备。我们另一个人开发的接口,是有一个程序,可以配置每一个模块,用固定的函数,参数是int。
结果和Lead会面,他上来就说,用enum(调用那个人的接口的时候转换成int)。我觉得有没有搞错。又发给我一个别人写的文档,说enum的好处。我看出来,那是给不变的设备用的,比如某个设备就开关两个状态,就写OFF, ON。但是,我这些设备有些是多个状态。有些设备,是互相可替换的(比如显卡),但是每个具有不同的状态数量。我的第一感觉就是,用enum不可行,因为需要在写程序的时候把json里面的字符串换成enum,然后我会有一些map,把上面来的指示的参数映射到enum,比如数据结构是
{系统模式(上面来的指令参数)1,设备A,enum 状态A1},{系统模式(上面来的指令参数)1,设备B,enum 状态B1}
这里面A1和B1是不同的类型,这个数据结构都没法构造,因为不同设备的enum空间不同。而且没法扩展。就是说,我基本上需要给每个设备写一个enum到字符串的映射程序。还不如直接用整数。
--
FROM 72.197.247.*
Rust
【 在 adoal 的大作中提到: 】
: 那么你用的是什么语言?
:
--
FROM 72.197.247.*
首先有不同类型的硬件,比如显卡和风扇不能用同样的enum吧,其次,显卡类有不同的显卡,不同供货商,不同的型号,就有不同的可选频率,怎么enum?比如用[f0, f1, f2], 新产品用了[f0', f1', f2', f3', f4'],怎么用enum控制?
用字符串也比enum强,因为可以兼容未来的新产品和型号。用enum,咋做?用union?显卡每次增加一个型号,就得改代码一次?
【 在 DoorWay 的大作中提到: 】
: 用enum。你的理由都是狡辩。
: 硬件都硬出来了,枚举值还能不确定?
: 用int是掩盖了问题。什么不同设备不同枚举空间,正是因为所有int处于同一个枚举空间——整数空间。可惜8还是16位,32位,64位没清楚。
: ...................
--
修改:bihai FROM 72.197.247.*
FROM 72.197.247.*
都是很小范围的整数来代表,因为是通过函数来控制设备。
Fan::Set(x);
GPU::Set(x);
具体对应的频率是显卡模块内部实现的,我只需要知道它允许哪些。比如第一个显卡[0:f0, 1:f1, 2:f2, 3:f3], 第二个显卡[0:f0', 1:f1', 2:f2', 3:f3', 4:f4', 5:f5']。那么在我的json里面,我就可以写
{ "Name": "GPU0",
"Setting":, 1,
}
这样,日后改用第二种显卡,我只需要改变配置文件,写个2即可。我的模块的代码就是要么读入字符串,要么读入整数。不同的产品用不同的显卡,用不同的配置文件。
【 在 superORC 的大作中提到: 】
: 那显卡对应的int范围是多少、风扇对应的int范围是多少,记录在哪里啊?不频繁变化的用enum,频繁变化的用数据库字典表。兼容这个说法就是前面某个朋友说的盖马桶理论,看不见不等于不臭。
: :
--
FROM 72.197.247.*
可复杂了。不是就一个enum,是一批。首先显卡,每个显卡一个enum类型;其次,还有别的部件,比如风扇,又是一批。20个设备,能搞出几百个类型。然后,显卡是一个类吧,但是我的模块是一个配置文件,读入一个字符串,变成哪个类的enum呢?费老劲了。
【 在 milksea 的大作中提到: 】
: enum与字符串转换有工具库做,不用自己来吧。strum什么的。
--
FROM 72.197.247.*
用Rust读配置文件非常容易,读入到一个struct里面非常直接,就对应到我的数据结构里。这个enum是不可能的,因为enum来自不同的类。配置文件只能读入数值和字符串。
现在Lead提出一个折中方案:虽然最后的调用是uint8,但是配置文件不放uint8,而是放入一个能够帮助找到这个uint8的参数,比如是一个字符串,或者数值(字符串也可以转换到数值)。对于显卡,存的就是频率。
对于别人的显卡控制模块,他们可能是0:500M, 1:625M, 2:750M等,那么在配置文件不存0,1,2,而是存750M。这样怎么知道是2呢?可以让别人提供另个统一的接口,得到2。然后我的数据结构在读入配置文件之后,构造vector里面存的是2。这里就没有enum什么事了。他说了,enum是静态模块用的,就是固定的几个状态。而我要对接的有大量的动态模块,不仅我不知道有哪些状态,开发这些模块的也不知道,没法用enum。连名字都没法起,叫FREQ_1, FREQ_2吗?已经失去了可读性了。也不能防止打错字了。而且和风扇的enum不一样,因为风扇是LEVEL_1, LEVEL_2。
现在回到那个写文档的人,我发现他没有考虑动态情况。
【 在 superORC 的大作中提到: 】
: 技术上,用配置文件来存对应关系是可以的,但是这个带来的另一个问题就是,你自己肯定很清楚怎么存放怎么用,但是因为不是写在代码里面的,接手你工作的人就得去了解怎么使用配置文件,而枚举更显得强制性一些。
: 做事上,最主要是你表达清楚你的想法,如果主管依旧不认可,那就接受这种设计。然后你要做的就是在这个条件下怎么处理好新硬件添加时候的代码更新,还有更新流程,是每硬件更新还是积累到周期更新,新硬件加入的审批流程,测试和发布流程。
: 最后,不要拘泥,具体问题上代码有最优解,但工程上是没有最优解的,都是各种妥协的结果,开心工作最重要。
--
FROM 72.197.247.*
只能说他在这个问题上一开始是犯傻了。看都没看我的设计文档,上来就直接说用enum。后来不是承认enum不可行了吗。
只要需要配置文件来存放配置信息,用enum就是多此一举,因为配置放在文件里,没有写在代码里,enum各种好处就没有了。同时因为不可预测的配置要求,enum是不显示的。他都没想过这些问题,就因为看了别人的一个文档就觉得要用enum,确实他犯傻了。当然,他很快纠正了,提出了更好的办法。哪怕用String也比enum强啊,反正配置文件里就是String。
【 在 superORC 的大作中提到: 】
: 我觉得他最大的问题不是技术上的,而是觉得主管是傻x。接受自己不理解的约束条件,也是一个架构师非常重要的能力。
--
FROM 72.197.247.*
这些设备对我的模块来说,都提供一些level而已。这些level对每个设备有不同的语义。比如3060是5个level,这五个可能对应五个频率。那么用enum起什么名字呢?这个时候名字已经失去了意义了:LELVE_0, LEVEL_1,这个可读吗?然后3070假定6个LEVEL。这个6个怎么命名?4080假定5个LEVEL,和3060用一样的enum?
【 在 zeus2615 的大作中提到: 】
: 如果你的所有设备都是只有一个用int表示的状态,那就
: enum Hardware {
: GPU(u16),
: ...................
--
FROM 72.197.247.*
没有性能压力,因为是一次性的,就是初始化的时候处理一下。就是说,初始化的时候读入配置文件,利用里面的字符串来得到每个设备对应每个状态的level,这个是uint8,即可,放入容器map里面。
后面所有操作就在容器里找到uint8。所以确实是字符串好,可读性高。
【 在 zeus2615 的大作中提到: 】
: 你说的这些工作量的问题都可以靠GPT或者util类来解决。譬如你的配置内容是GPU_1、FAN_1,这是小事。除非有存储/传输成本压力,或者读写性能压力,否则我觉得字符串好太多了
: 【 在 bihai 的大作中提到: 】
: :......
: ...................
--
FROM 72.197.247.*