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

服务端复杂项目超长代码该如何组织呢?

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

    如题,最近我在整理之前写的项目,发现有一个接口的代码越发出现失控的趋势(一个请求已经一百多行了),想请教一下大家是怎么处理这种问题的

    项目是一个社区程序,用户回复一个主题后首先要

    1. 对内容进行审核(看是否有黄暴或者攻击词汇)
    2. 筛选关键 tag
    3. 如果附带图片,图片内容审核
    4. 如果是匿名回帖还要生成随机昵称
    5. 如果是匿名私信还要处理私信内容
    6. 处理回复者和发帖人的积分变动
    7. 如果主贴超过一定回复数同步到其他社交平台等等
    8. 数据库处理入库

    要做的内容非常的多,但是能抽象成单独函数的貌似只有审核和生成昵称,其他大部分都无法复用

    但是我总觉得一个请求接口就这么老长,是不是我写项目的方式不对?

    请各位大神指教

    项目使用 Flask+Mongo

    60 条回复    2020-08-06 10:13:50 +08:00
    seki
        1
    seki   54 天前
    你的逻辑就是这样,那就这么写咯

    如果想不到怎么优化就先别优化,过早优化的效果不一定会那么好
    hunter2015
        2
    hunter2015   54 天前
    拉面条就对了,优化,啥是优化
    emeab
        3
    emeab   54 天前 via iPhone
    才 100 多行嘛 还好啦
    lower
        4
    lower   54 天前
    才一百多行……就敢叫超长代码?😀
    vertigo
        5
    vertigo   54 天前
    @lower 啊?不然呢...我一般超过 40 行就有点受不了了
    IceBay
        6
    IceBay   54 天前 via iPhone
    无法复用为什么就不能拆呢?
    kop1989
        7
    kop1989   54 天前
    没想好就先别动。千万别把代码设计和所谓“行数”做强关联。
    你把他们都抽象出来看似接口只有几行了,其实是掩耳盗铃。
    buffzty
        8
    buffzty   54 天前   ❤️ 1
    四十行就受不了只能说明你没写过大项目. 你去看看 mysql oracle 源码
    四十行? 你说的是一个小函数里面的括号吗
    gz911122
        9
    gz911122   54 天前
    不要过分拆分看着更累.
    逻辑清晰按步骤走就行了
    wysnylc
        10
    wysnylc   54 天前
    经验太少,过几年你就知道怎么写屎了
    angryfish
        11
    angryfish   54 天前
    感觉逻辑挺清晰的啊
    ppphp
        12
    ppphp   54 天前
    没文档不清楚上下文就是这样的,吃过的奥利给多了,就香起来了
    vertigo
        13
    vertigo   54 天前
    @kop1989 是的,我也是这样理解的,不能为了设计而设计.所以才有这种疑惑
    lijsh
        14
    lijsh   54 天前
    积分变动和同步社交内容这个可以搞成事件或者消息吧
    Vegetable
        15
    Vegetable   54 天前
    100 行的超长代码可还行?
    每一个步骤可以分开,哪怕不能复用也可以抽象一下,不是过度设计,只是为了让逻辑更有层次方便理解。不会各种语句堆在一起,看着眼花。
    xuanbg
        16
    xuanbg   54 天前
    每个功能抽象一个方法,接口负责调用这些方法。有些方法还可以异步处理,进一步减少接口响应时间。
    WebKit
        17
    WebKit   54 天前 via Android
    40 行??我移动端传参数就 10 几行
    VictorJing94
        18
    VictorJing94   54 天前
    .............骚年,见过几万行的函数嘛
    hoyixi
        19
    hoyixi   54 天前
    你这里好几个步骤都是子功能 or 单独模块,别的地方都会用到,你这里不过调用一下罢了
    Jackeriss
        20
    Jackeriss   54 天前 via iPhone
    不是能复用才抽函数呀,函数可以让代码逻辑更清晰
    EscYezi
        21
    EscYezi   54 天前 via iPhone
    按功能拆分函数,就算无法复用以后维护也更容易
    libook
        22
    libook   54 天前
    出现问题或确定会出现问题的时候再考虑优化,把精力放在当下最重要的事情,如果实在没有事情可做,就对自己的系统做压力测试、可用性测试、边界测试,提前发现些问题,再根据问题的影响排优先级,从高优先级的问题开始解决优化。

    如果代码可读性上有问题,就适当调整代码结构、增加注释,少用些奇淫技巧,少偷懒。
    skypyb
        23
    skypyb   54 天前 via Android
    你说的这些审核啊、积分变动啊、内容同步啊。 后续需求拓展起来应该是可以有一大堆代码的。
    需要保证先后关系的如 审核- 匿名去敏 - 入库,可以解耦成责任链, 后续往上加东西对其他的代码改动就不会那么大。 其他的像是内容同步和积分变动这种,考虑观察者模式, 发个事件 /消息之类的
    vertigo
        24
    vertigo   54 天前
    @lijsh
    @xuanbg
    @hoyixi
    @Jackeriss
    @EscYezi

    我想表达的意思是,比如一个函数是

    ```python
    def foo():
    print('a')
    print('b')
    print('c')
    ```
    改成
    ```
    class methods:
    def a(self):
    print('a')
    def b(self):
    print('b')

    def foo():
    bar = methods()
    bar.a()
    bar.b()
    print('c')
    ```
    反而会凭空多出复杂度出来,又少了可读性.比较困扰
    但是看了上面其他大佬的回答,那么看来基本就是这个样子啦,那就保持原样这样吧
    vertigo
        25
    vertigo   54 天前
    @skypyb 如上条回复,我觉得可能只是把代码换了一个位置,真改起来来回找文件感觉更麻烦
    vertigo
        26
    vertigo   54 天前
    @skypyb 观察者模式这种方式很不错,我没有想到,谢谢大佬
    Hanggi
        27
    Hanggi   54 天前
    复杂的代码一定要装进黑盒,避免污染到其他功能,对外接口要简单清晰,里面爱怎么整怎么整。
    Veneris
        28
    Veneris   54 天前
    审核,匿名抽象出工具类,大概率会复用
    积分变动,同步到其他平台等使用消息队列异步处理
    btw,其实这个代码行数不多
    ZehaiZhang
        29
    ZehaiZhang   54 天前
    那你是没见我同事七千行的代码
    msaionyc
        30
    msaionyc   54 天前
    其实代码长不是问题,你这个抽方法,抽模块都很容易解决,最难解决的是慢接口,你这审查图片和审查文本,查表,落表,筛选这么多流程,后期数量大了,用户体验会非常差
    有几个地方可以优化:
    1.匿名的随机昵称是否需要使用到时再生成,可不可以预生成
    2.增加积分功能抽模块,消息?
    3.同步到其他社交平台也可以抽成模块,异步去做,或者定时任务去做
    4.图片处理一定要在这个逻辑里同步做吗?是否可以异步做,然后再处理掉
    vertigo
        31
    vertigo   54 天前
    @msaionyc
    1. 随机昵称这个必须同步做,因为用户回复完立刻就显示出来了
    2. 同步平台的确可以异步或者定时任务完成,这个我事先没想到,nice.
    3. 积分想了想的确可以抽象
    4. 图片和内容审查就比较纠结,因为前有 soul 那档子烂事...如果做成异步或定时的,就怕有恶意用户发帖截图删举报一条龙(虽然法律上可以很直接追责,但是一旦发生产品基本也 GG 了)这是我完全独立运营和开发的项目,我觉得这种风险还是要权衡下
    bugmakerxs
        32
    bugmakerxs   54 天前
    看到这个数了数公司那个大接口的代码。。。2000 多行一个方法,不敢动不敢动
    Rwing
        33
    Rwing   54 天前
    设计模式
    RadishWind
        34
    RadishWind   54 天前
    抽象成 workflow,然后复用 workflow 中的 step
    vertigo
        35
    vertigo   54 天前
    @bugmakerxs 我整个项目一共 900 多行代码(包含注释和空行).....你说的那个接口肯定 java 写的吧
    Youen
        36
    Youen   54 天前
    不一定非要短.

    https://news.ycombinator.com/item?id=18772873

    // ==================================================================
    // PLEASE DO NOT ATTEMPT TO SIMPLIFY THIS CODE.
    // KEEP THE SPACE SHUTTLE FLYING.
    // ==================================================================
    h123123h
        37
    h123123h   54 天前
    我见过一个项目很多代码都是几千行的,第二天果断跑路了
    coderxy
        38
    coderxy   54 天前
    我最夸张的一个方法里 3000 行代码。 你这不算什么
    wellsc
        39
    wellsc   54 天前 via iPhone
    两三千行的函数见过嘛
    xuxuzhaozhao
        40
    xuxuzhaozhao   54 天前
    100 多行也叫超长代码,玩呢?我现在正在改一个 800 多行的函数。
    msaionyc
        41
    msaionyc   54 天前
    @vertigo 第一点预生成的意思是提前生成好,到时候直接取,但想了想这个操作也是不太需要的,生成昵称这个操作基本 0 耗时
    raaaaaar
        42
    raaaaaar   54 天前 via Android
    一个函数只做函数名所表示的功能。只要能做到这一点,函数长度不要过于要求。
    zhuweiyou
        43
    zhuweiyou   54 天前
    100 毛毛雨,几千行的都写过。
    bccoder
        44
    bccoder   54 天前 via Android
    我提交的参数有 100 多个,加上校验逻辑什么的,好几百行
    csl1995
        45
    csl1995   54 天前
    一个函数上千行。。。
    luxinfl
        46
    luxinfl   54 天前
    jdk 和 spring 里面也有很多超长的源码,这都不是事
    amundsen
        47
    amundsen   54 天前
    都是一把梭,又不是不能用~
    rockyou12
        48
    rockyou12   54 天前
    从你描述的业务来看,其实 100 行不算多啊……就码 if else if else 都要码很多行,逻辑清晰就别乱优化行数了
    zgzb
        49
    zgzb   54 天前
    现在硬盘容量足够大,只要功能多,界面美观,写成屎也没关系
    EminemW
        50
    EminemW   54 天前 via iPhone
    我司有个几千行的接口,一个函数几百行,我改了几次,最后怕改出啥问题,就回退了
    leafdream
        51
    leafdream   54 天前
    一个文件 8000 行的路过
    nthhdy
        52
    nthhdy   54 天前
    只要不影响阅读和思考,单个函数长一些是没问题的。
    抽函数的另一个考量是,是不是有一些部分是独立的概念,从而能当作新的 building block,简单的说就是看它能不能被重用。行数不是“硬指标”。
    不用太教条了。
    Jooooooooo
        53
    Jooooooooo   54 天前
    八个模块八个方法

    主方法就八行?

    挺清晰的
    zjddp
        54
    zjddp   53 天前
    说个歪的,换个带鱼屏,竖过来用就不超长了手动狗头
    NCZkevin
        55
    NCZkevin   53 天前
    写的一个处罚接口 快 1000 行,感觉随时可能出问题
    vertigo
        56
    vertigo   53 天前
    @zjddp 有,脖子疼
    taowen
        57
    taowen   53 天前
    ```
    对内容进行审核(看是否有黄暴或者攻击词汇)
    筛选关键 tag
    如果附带图片,图片内容审核
    如果是匿名回帖还要生成随机昵称
    如果是匿名私信还要处理私信内容
    处理回复者和发帖人的积分变动
    如果主贴超过一定回复数同步到其他社交平台等等
    数据库处理入库
    ```

    这个例子举得挺好的。把所有的这些逻辑都实现在帖子回复这个接口里的问题是什么?如果没有问题,改进也就没有收益。楼主提出了抽函数貌似也无法复用,那还需要抽函数吗? 这里有两个关键词

    * 抽函数
    * 复用

    为什么手段一定是抽函数,为什么目标是复用? 这种一竿子写到底的写法的问题是什么? 如果问题不清楚,直接拿抽函数这个解决方案去套,就可能缘木求鱼了。

    所以希望楼主或者其他回复的人,能够举一些具体场景的具体例子,这样的写法会带来的非常具体的问题。只有针对这些问题才有讨论价值。一段静态的代码文本,没有对错好坏之分。只有带入了具体的场景里,有针对性的问题,才有讨论意义。
    vertigo
        58
    vertigo   53 天前   ❤️ 1
    @taowen 我认为一竿子写到底方法的问题是"边界感",细想一下,我们看代码的第一眼并不是精细到文字,而是一个个矢量块(常见例子是 3d 游戏渐进式加载,先是一个大立方体块,接着更多细节,最后才是具体贴图)

    作为不常修改的稳定模块(不常改就记不住),突然想加东西时第一眼就是一长条色块,接下来需要自己通读一下代码才可以知道哪里改

    例:添加一个自动添加水印功能,我需要找到图片审核后,生成昵称前,然后插入逻辑,但是如上说,纯文字代码需要彻底读完或者读到大班才能知道在哪里动手,效率有点尴尬.(并且随着代码变大,每次这个通读过程会越来越多)

    而极端的抽离逻辑后,我们视觉上是一个个短色块,此时我们只要读取 function name 就能大致知道这个模块是不是该改动(类似数据库加 index 了),这是我觉得抽象逻辑的好处

    实际上我也认同楼上其他大佬说的,能不乱改还是不乱改,只是想知道有没有两者结合的方法
    Ryzebo
        59
    Ryzebo   53 天前
    其实,作为老实人,
    你是面向薪资编程,还是面向项目编程,还是面向自己编程,还是面向加班编程?
    vertigo
        60
    vertigo   52 天前
    @Ryzebo 这个是我个人项目呀,面向彩虹屁编程
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2723 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 13:41 · PVG 21:41 · LAX 06:41 · JFK 09:41
    ♥ Do have faith in what you're doing.