V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ZekeChin
V2EX  ›  程序员

"动态"编程逻辑:这种灵活性的合理性有多大

  •  2
     
  •   ZekeChin · 201 天前 · 3906 次点击
    这是一个创建于 201 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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_namelast_name)。现在的情况是,代码被修改以添加大量的if语句(例如:if column_name == "full_name": ...),向后兼容性变得非常困难。

    我有一种感觉,所有这些"动态"的代码在理论上听起来很聪明、很酷,但实际上它变成了一个负担。这是一个众所周知的问题,还是我理解错了?我想向我的团队阐述我为什么认为这是一个问题,但我缺乏参考文献。你能提供一些我可以用来分享我的观点的信息吗?这种做法有一个名字吗?有关代码"动态性"的最佳实践是什么?

    28 条回复    2024-05-09 21:31:59 +08:00
    InkStone
        1
    InkStone  
       201 天前   ❤️ 16
    这就是“复杂性不会消失,只会转移”。

    最佳实践应该就是不要盲目追求灵活性,像数据格式这种东西就应该老老实实约定好固定下来……API 和 DAO 中间还是需要中间层做解耦,不要搞什么 API 的字段直接对应到数据库的飞机。
    yexian
        2
    yexian  
       201 天前
    不如在字段里存 json ?
    dddd1919
        3
    dddd1919  
       201 天前
    eval 一时爽
    codehz
        4
    codehz  
       201 天前 via iPhone
    说明抽象程度还不够,无法对整个事情进行建模(就像写代码使用动态类型,很多时候只是因为类型系统不够完善,无法在类型层面上描述具体项目的约束)
    zhtyytg
        5
    zhtyytg  
       201 天前
    一个最简单的外行指导内行逻辑就是:万物皆可动态 以及 万物皆需封装
    前者会让所有本来简单直接的设计变成一个臃肿的怪物
    后者会让开发进程无限拉长直至项目失败
    shunia
        6
    shunia  
       201 天前
    不是很懂,除非有工具能自动映射数据库表结构为代码,否则不都是动态查表的吗?不管你是写 SQL 查询还是用了什么高级工具或者流程,最终数据库表字段一改,你查询代码或者 DAO 层就是得跟着变化吧。只是说这个动态的过程是反映在业务代码层,还是反映在数据库中间层部分而已?

    另外如果帖主提到的这种情况,不是落在每一处业务代码中,而是也分层做了隔离呢?那还算动态吗?
    james122333
        7
    james122333  
       201 天前 via Android
    事实上提到的也并不动态 只有静态的才会一直在那边 if 一个一个判别
    james122333
        8
    james122333  
       201 天前 via Android
    动态只做半套说累不是其来有自吗
    murmur
        9
    murmur  
       201 天前
    光批判不贴代码不是跟耍流氓一样么

    原文也没贴

    他的例子完全不懂是什么意思

    按我的理解,国内的低代码写法他看到要骂娘,尤其是要兼容各种数据库,还得能切换的
    meeop
        10
    meeop  
       201 天前
    项目经验上来看,大多数“动态”xx 的功能是不合理的过度设计

    动态的意思是某些逻辑无法在开发时确定,或者需要支持开发好后灵活变更

    绝大多数场景,就是单纯的没想好系统模型设计而导致的
    除非确实是一个需要支持灵活变化的部分才需要动态话(典型场景是一个动态表单,运营可以灵活配置创建,免开发)
    iOCZS
        11
    iOCZS  
       201 天前
    得到自由的同时,就会陷入自由的混乱
    blackmirror
        12
    blackmirror  
       201 天前
    这种就是自己轻松一点,只能苦一苦别人了
    wclssdn
        13
    wclssdn  
       201 天前
    也分实际场景吧,如果是提供的云数据库的业务,那就是无法提前知道用户会创建什么样的数据结构。 但还要提供 API 去操作数据库。
    如果要针对特定用户的数据表做处理,例如拆分姓名,那就应该让用户自行的创建一个数据前置、后置处理器去处理。
    如果场景中没有这个“用户”,那就应该由业务自行的来抽象一个,哪个是这个“用户”,例如 A 业务、B 业务。

    总结一下:运用领域思维去设计总是无往不利,比如这个场景:总得有人知道数据结构吧? 谁知道谁处理就不会有这种疑问了。
    leonshaw
        14
    leonshaw  
       201 天前
    合理性在于能把复杂逻辑甩给别人。
    tool2dx
        15
    tool2dx  
       201 天前
    @murmur “他的例子完全不懂是什么意思”

    中文译文不太好理解,英文原文还是容易理解的。

    就是把一个 user.full_name 字段拆分成两个 api, 单独返回 first_name 和 last_name 。
    ny562kPWNJK9g86f
        16
    ny562kPWNJK9g86f  
       201 天前
    避免过度设计,该踢正步就踢正步,该跑步时就应该跑步,在技术上不要太过于迂腐了。
    crz
        17
    crz  
       201 天前
    按例子是 '数据库 -> 访问层 -> 应用层' 的抽象,访问层处理具体数据已经超出设计了,另外 full_name 的设计看起来是一开始把脑袋拍响了?
    lujiaxing
        18
    lujiaxing  
       201 天前
    动态到头了, 其实就是 IDE 跟编程语言...
    我什么都不写就是最灵活的.
    zhazi
        19
    zhazi  
       201 天前   ❤️ 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 这种代码
    bojue
        20
    bojue  
       201 天前
    我们是参考 critical 开发的一套,会基于表和表关系抽取两套核心对象 Entity 和 Query ,动态绑定一套事件机制 Create,Delete,update,getObjectByName,ByFilter,ById 类似的架构,底层很灵活,前段应用层通过抽象的 API 屏蔽掉 SQL 层
    lambdaq
        21
    lambdaq  
       201 天前
    用户查询可以在不同的数据库上执行,而我们并不需要提前知道数据库上有哪些表格/列


    mongodb: ......

    es: .....

    pg hstore: ....

    pg jsonb: .....

    innodb json: .....

    sqlite: https://sqlite.org/draft/jsonb.html
    murmur
        22
    murmur  
       201 天前
    @tool2dx 一个 split 解决的问题为什么用到 if/else ,这是我没法理解的
    NoOneNoBody
        23
    NoOneNoBody  
       201 天前
    GUI 编程,特别是主观输入(如搜索),是需要很多动态的判断,或者说人机交互
    如果“动态”不够,搜索会限定在一些固有条件内,搜索结果会“混乱”,这个混乱指的是使用者的感受,而不是编程者的认为

    例如媒体管理搜索,输入“东野圭吾”,在输入者的角度,他想搜索的是“根据东野圭吾小说改编的影视作品”,这个搜索方向是 tag ,因为 title 基本不存在“东野圭吾”这个关键词,后者搜不到结果

    人(用户)是万变的,如果模式固定了,也限定了人只能按有限的固定方式交互,体验难以提升
    很需要对使用者的输入进行一次“理解”,再选择对应的路子,随着 AI 的发展,这项工作可以交给 AI 优化,但目前来说还不算好的方案,一是本地部署还不容易,二是 AI 理解还不算强,例如上例“东野圭吾”几个字并不是一个句子,AI 需要广泛知识才能“领悟”,最重要还是 AI 成本还很高

    “东野圭吾”还存在变数,简体、繁体、日语汉字……等等,这里刚好繁体和日语汉字是相同的,但“黑泽明”呢

    我自写的一个媒体管理就遇到上述问题(还有更多),导致输入搜索这块一直做不好,是目前最大瓶颈
    yy77
        24
    yy77  
       201 天前
    感觉应该是对于每个不同类型的数据写类,然后通过依赖注入来在上层保证操作的统一性。
    teaegglove
        25
    teaegglove  
       201 天前 via Android
    Less is more
    liuidetmks
        26
    liuidetmks  
       201 天前
    全自动化 不如 半自动化。
    james122333
        27
    james122333  
       201 天前 via Android
    @teaegglove

    这也可以讲成
    三十辐 共一毂 当其无 有车之用
    james122333
        28
    james122333  
       201 天前 via Android
    @teaegglove

    其实我是觉得中文讲的比较贴切
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1040 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:42 · PVG 04:42 · LAX 12:42 · JFK 15:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.