reddit 刷到的一个帖子发现 原来大家都有一样的烦恼,V 站的朋友们怎么看 https://www.reddit.com/r/AskProgramming/comments/1cmkf0m/dynamic_logic_in_code_is_this_flexibility_worth_it/
译文如下
在我最近的一份工作中,我注意到我们的代码库中有大量的"动态"逻辑。例如,我们通过动态提取列名来管理具有不同模式的多个 SQLite 文件,而不是为每个模式进行版本控制。基本上,用户查询可以在不同的数据库上执行,而我们并不需要提前知道数据库上有哪些表格/列。这样的优点是我们不需要为每个数据库写新的逻辑,创建这些数据库的团队也不需要与我们(后端)同步,API 可以"直接"透明地访问数据库内容。所以这种策略被认为是"更灵活的"。
然而,我发现这使得理解、测试和编写代码文档变得更加困难。向后兼容性的提供也变得更困难,或者在必要时定制后端的行为也更为复杂。例如,假设我们在数据库上有一个user.full_name
列,但 API 必须返回两个分开的字段(first_name
和last_name
)。现在的情况是,代码被修改以添加大量的if
语句(例如:if column_name == "full_name": ...
),向后兼容性变得非常困难。
我有一种感觉,所有这些"动态"的代码在理论上听起来很聪明、很酷,但实际上它变成了一个负担。这是一个众所周知的问题,还是我理解错了?我想向我的团队阐述我为什么认为这是一个问题,但我缺乏参考文献。你能提供一些我可以用来分享我的观点的信息吗?这种做法有一个名字吗?有关代码"动态性"的最佳实践是什么?
1
InkStone 206 天前 16
这就是“复杂性不会消失,只会转移”。
最佳实践应该就是不要盲目追求灵活性,像数据格式这种东西就应该老老实实约定好固定下来……API 和 DAO 中间还是需要中间层做解耦,不要搞什么 API 的字段直接对应到数据库的飞机。 |
2
yexian 206 天前
不如在字段里存 json ?
|
3
dddd1919 206 天前
eval 一时爽
|
4
codehz 206 天前 via iPhone
说明抽象程度还不够,无法对整个事情进行建模(就像写代码使用动态类型,很多时候只是因为类型系统不够完善,无法在类型层面上描述具体项目的约束)
|
5
zhtyytg 206 天前
一个最简单的外行指导内行逻辑就是:万物皆可动态 以及 万物皆需封装
前者会让所有本来简单直接的设计变成一个臃肿的怪物 后者会让开发进程无限拉长直至项目失败 |
6
shunia 206 天前
不是很懂,除非有工具能自动映射数据库表结构为代码,否则不都是动态查表的吗?不管你是写 SQL 查询还是用了什么高级工具或者流程,最终数据库表字段一改,你查询代码或者 DAO 层就是得跟着变化吧。只是说这个动态的过程是反映在业务代码层,还是反映在数据库中间层部分而已?
另外如果帖主提到的这种情况,不是落在每一处业务代码中,而是也分层做了隔离呢?那还算动态吗? |
7
james122333 206 天前 via Android
事实上提到的也并不动态 只有静态的才会一直在那边 if 一个一个判别
|
8
james122333 206 天前 via Android
动态只做半套说累不是其来有自吗
|
9
murmur 206 天前
光批判不贴代码不是跟耍流氓一样么
原文也没贴 他的例子完全不懂是什么意思 按我的理解,国内的低代码写法他看到要骂娘,尤其是要兼容各种数据库,还得能切换的 |
10
meeop 206 天前
项目经验上来看,大多数“动态”xx 的功能是不合理的过度设计
动态的意思是某些逻辑无法在开发时确定,或者需要支持开发好后灵活变更 绝大多数场景,就是单纯的没想好系统模型设计而导致的 除非确实是一个需要支持灵活变化的部分才需要动态话(典型场景是一个动态表单,运营可以灵活配置创建,免开发) |
11
iOCZS 206 天前
得到自由的同时,就会陷入自由的混乱
|
12
blackmirror 206 天前
这种就是自己轻松一点,只能苦一苦别人了
|
13
wclssdn 206 天前
也分实际场景吧,如果是提供的云数据库的业务,那就是无法提前知道用户会创建什么样的数据结构。 但还要提供 API 去操作数据库。
如果要针对特定用户的数据表做处理,例如拆分姓名,那就应该让用户自行的创建一个数据前置、后置处理器去处理。 如果场景中没有这个“用户”,那就应该由业务自行的来抽象一个,哪个是这个“用户”,例如 A 业务、B 业务。 总结一下:运用领域思维去设计总是无往不利,比如这个场景:总得有人知道数据结构吧? 谁知道谁处理就不会有这种疑问了。 |
14
leonshaw 206 天前
合理性在于能把复杂逻辑甩给别人。
|
15
tool2dx 206 天前
@murmur “他的例子完全不懂是什么意思”
中文译文不太好理解,英文原文还是容易理解的。 就是把一个 user.full_name 字段拆分成两个 api, 单独返回 first_name 和 last_name 。 |
16
ny562kPWNJK9g86f 206 天前
避免过度设计,该踢正步就踢正步,该跑步时就应该跑步,在技术上不要太过于迂腐了。
|
17
crz 206 天前
按例子是 '数据库 -> 访问层 -> 应用层' 的抽象,访问层处理具体数据已经超出设计了,另外 full_name 的设计看起来是一开始把脑袋拍响了?
|
18
lujiaxing 206 天前
动态到头了, 其实就是 IDE 跟编程语言...
我什么都不写就是最灵活的. |
19
zhazi 206 天前 1
赞同 7 楼所说的
可能是这个提出问题的人抽象的不到位,所以写出了不灵活的代码 打个比方 你们是一家做平台的公司, 要与客户来对接, 你的第一个客户定义了的名称需要用 user.full_name 你的第二个客户定义了的名称需要用 user.first_name 和 last_name 你的建模是客户如何描述他的业务字段,而不是判断客户的字段 你的建模定义为 客户 1 field:'name' column_name:name_str type: string value:'zhangsan' 客户 2 field:'name' column_name:name_obj type: object value:{'first_name':'zhang','last_name':'san'} 通过 type 统一了两个客户对象的建模,不需要写出 if column_name == full_name 这种代码 |
20
bojue 206 天前
我们是参考 critical 开发的一套,会基于表和表关系抽取两套核心对象 Entity 和 Query ,动态绑定一套事件机制 Create,Delete,update,getObjectByName,ByFilter,ById 类似的架构,底层很灵活,前段应用层通过抽象的 API 屏蔽掉 SQL 层
|
21
lambdaq 206 天前
用户查询可以在不同的数据库上执行,而我们并不需要提前知道数据库上有哪些表格/列
mongodb: ...... es: ..... pg hstore: .... pg jsonb: ..... innodb json: ..... sqlite: https://sqlite.org/draft/jsonb.html |
23
NoOneNoBody 206 天前
GUI 编程,特别是主观输入(如搜索),是需要很多动态的判断,或者说人机交互
如果“动态”不够,搜索会限定在一些固有条件内,搜索结果会“混乱”,这个混乱指的是使用者的感受,而不是编程者的认为 例如媒体管理搜索,输入“东野圭吾”,在输入者的角度,他想搜索的是“根据东野圭吾小说改编的影视作品”,这个搜索方向是 tag ,因为 title 基本不存在“东野圭吾”这个关键词,后者搜不到结果 人(用户)是万变的,如果模式固定了,也限定了人只能按有限的固定方式交互,体验难以提升 很需要对使用者的输入进行一次“理解”,再选择对应的路子,随着 AI 的发展,这项工作可以交给 AI 优化,但目前来说还不算好的方案,一是本地部署还不容易,二是 AI 理解还不算强,例如上例“东野圭吾”几个字并不是一个句子,AI 需要广泛知识才能“领悟”,最重要还是 AI 成本还很高 “东野圭吾”还存在变数,简体、繁体、日语汉字……等等,这里刚好繁体和日语汉字是相同的,但“黑泽明”呢 我自写的一个媒体管理就遇到上述问题(还有更多),导致输入搜索这块一直做不好,是目前最大瓶颈 |
24
yy77 205 天前
感觉应该是对于每个不同类型的数据写类,然后通过依赖注入来在上层保证操作的统一性。
|
25
teaegglove 205 天前 via Android
Less is more
|
26
liuidetmks 205 天前
全自动化 不如 半自动化。
|
27
james122333 205 天前 via Android
|
28
james122333 205 天前 via Android
|