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

重构屎山的痛。我已经坚持了三四天了,必须要在这里发泄下,不然会炸。

  •  1
     
  •   villivateur · 2023-09-14 14:32:13 +08:00 · 12418 次点击
    这是一个创建于 415 天前的主题,其中的信息可能已经有所发展或是发生改变。

    因产品整合需求,要把一个 C++ Qt 写的上位机软件重构到 PyQt 中。主管不同意用现有框架直接包装原有的 Qt 程序,要我直接按需求重构。(可能主管也早就意识到了这个屎山迟早会炸)

    这个屎山有多屎呢:

    1. 十年前的老代码,经手过无数人
    2. 编译一下,平均一个文件十个 warning ,不乏长度为 9 的数组访问第 9 个变量这种奇葩事
    3. 变量名潇潇洒洒,驼峰的,下划线的,大写的,小写的,混合的
    4. 真正实现了“低内聚,高耦合”,三个线程,几十个函数,共用一个一百多行的结构体……
    5. 有个功能是初始化两个设备(互相独立),两个设备各要执行几个函数,结果代码里面,是 A 设备先执行两个函数,B 再执行两个,再执行 A 的……不懂的人还以为这两个设备有啥奇妙的联系。
    6. 驱动模块和业务模块居然用 extern 来共享一个变量……

    还有很多……

    给大家欣赏一下屎山的一角:

    scanThreadData->mcuFirmWare_path = "";    //清空 mcu 固件路径
    scanThreadData->mcuFirmWare_path = ScanFirewareBin(IS_NGFDFILE, ProductCodeStr);
    

    这个 mcuFirmWare_path 是个 string 类型的数据,我 TM 谢谢他先给我清空,还煞有其事地写个注释。

    看这个代码,每看一行我都要理一下自己的脾气。

    102 条回复    2023-09-16 14:59:43 +08:00
    1  2  
    codeself
        1
    codeself  
       2023-09-14 14:35:40 +08:00
    试试分模块 or 分方法,让 ai 帮你重构
    sundev
        2
    sundev  
       2023-09-14 14:38:03 +08:00
    说实话,能重构成功的可能性真的很小。
    我这边维护的一个 asp 的代码,十八年的代码,一个文件几万行代码,一个函数几千行常有,看都看不来。我也曾尝试过用新语言重写,后来放弃了。
    shangwuli
        3
    shangwuli  
       2023-09-14 14:38:23 +08:00
    你们会定期做代码评审吗?
    tyzandhr
        4
    tyzandhr  
       2023-09-14 14:41:51 +08:00 via Android   ❤️ 5
    低内聚,高耦合,有点绷不住
    putyy
        5
    putyy  
       2023-09-14 14:42:54 +08:00
    屎山一角属实厉害
    ygtq
        6
    ygtq  
       2023-09-14 14:46:10 +08:00
    主管不同意用现有框架直接包装原有的 Qt 程序,要我直接按需求重构
    那就直接回复说,重构需要 x 个工作日( x 算进自己的从屎山代码恢复的时间)
    greatbody
        7
    greatbody  
       2023-09-14 14:50:33 +08:00
    @sundev 这个可以考虑使用绞杀者模式。
    mightybruce
        8
    mightybruce  
       2023-09-14 14:50:48 +08:00
    PyQt 也没多好吧, 那你自己不要写屎山就行。
    txhwind
        9
    txhwind  
       2023-09-14 14:51:01 +08:00   ❤️ 2
    对能工作的老代码,以包装为主,尽量别改动内部。实在要大改,建议重写。
    villivateur
        10
    villivateur  
    OP
       2023-09-14 14:52:00 +08:00
    @sundev 已经重构了一部分了,还是有可能重构成功的,毕竟代码量也就几千行
    daimubai
        11
    daimubai  
       2023-09-14 15:00:56 +08:00
    十多年的代码如果重构,是不是也需要完整的测试一次呢
    zjj19950716
        12
    zjj19950716  
       2023-09-14 15:01:58 +08:00   ❤️ 1
    这时候心态很重要 能跑就行 不管是人还是代码
    tool2d
        13
    tool2d  
       2023-09-14 15:04:41 +08:00
    我前几天刚写了一堆"屎山", 主要是业务需求太复杂,一大堆电子表格的复合查询 SQL ,加上一堆数据透视表。

    需求太杂,代码就开始放飞自我了。

    等着空了重构一下,要不然几个月后,我自己都看不懂。
    k9982874
        14
    k9982874  
       2023-09-14 15:06:55 +08:00   ❤️ 2
    慢慢来呗,反正给钱干啥不是干。另外重构的时候别太梗直,新代码争取也搞成屎山,以后你就是唯一懂这坨屎的人,在公司就稳了。
    Chad0000
        15
    Chad0000  
       2023-09-14 15:09:34 +08:00 via iPhone
    我重构两年了,国外电信公司。在这边就是躺平吃老本儿的行业,我带着团队重构。把代码一点点转移出来。
    shyrock
        16
    shyrock  
       2023-09-14 15:10:10 +08:00   ❤️ 16
    你现在的吐槽都没有在点上。
    实际上代码难看、结构混乱根本不是问题。
    真正的问题是缺少关键信息:
    这座屎山还在被外界使用的功能到底有哪些?
    有哪些你看上去是依托答辩的代码其实改掉就会在不确定的时间导致业务崩溃?
    HackerTerry
        17
    HackerTerry  
       2023-09-14 15:22:02 +08:00
    @Chad0000 羡慕国外程序员,请问您在哪个国家工作?
    Chad0000
        18
    Chad0000  
       2023-09-14 16:09:45 +08:00 via iPhone
    @HackerTerry #17
    新西兰
    dog82
        19
    dog82  
       2023-09-14 16:22:24 +08:00
    为啥要重构,直接在屎山上拉新屎呗
    dif
        20
    dif  
       2023-09-14 16:26:03 +08:00
    屎山的精髓就是一代又一代人源源不断往上拉。所以重构啥,一堆人拉的屎才好看。只要不塌接着拉
    IBN5100
        21
    IBN5100  
       2023-09-14 16:27:02 +08:00
    还有注释 还不感恩戴德
    ma836323493
        22
    ma836323493  
       2023-09-14 16:34:46 +08:00
    哈哈,这有啥, 当年我重构了 一条 50kb 的 sql
    lDqe4OE6iOEUQNM7
        23
    lDqe4OE6iOEUQNM7  
       2023-09-14 16:41:08 +08:00
    写代码的最高境界就是屎上雕花,屎山不是一日建成的,加油,奥利给
    ryd994
        24
    ryd994  
       2023-09-14 16:51:09 +08:00 via Android
    @villivateur #10 你是什么时候产生了能成功的错觉?这种症状多久了?

    不是代码写完就完事的啊,之后 debug 才是大坑。自己跑通了之后还得联合上下游组件调试。内部调试完之后还要上线。上线折腾个十天半个月的很正常。最怕是上完线了,一周之后,某个没人知道的 corner case 炸了。

    Linus:If it's a then it's not a bug, it becomes a feature. You can't just fix the bug and say that's undefined behavior.
    ryd994
        25
    ryd994  
       2023-09-14 16:52:44 +08:00 via Android   ❤️ 2
    Linus:If it's a bug that people rely on, then it's not a bug, it's a feature.

    iweus
        26
    iweus  
       2023-09-14 17:08:15 +08:00
    这有啥,14 年前的代码依然在维护,只要不崩就没事
    xiangyuecn
        27
    xiangyuecn  
       2023-09-14 17:10:42 +08:00
    钱到位,屎珍香😅
    cy18
        28
    cy18  
       2023-09-14 17:14:43 +08:00
    具体情况不清楚,不过上位机是屎山,下位机的代码估计也好不了,大概率有很多莫名其妙的逻辑是用来上下位机配合的,搞不好还需要通过软件处理什么硬件 bug...
    祝 LZ 好运...
    villivateur
        29
    villivateur  
    OP
       2023-09-14 17:18:21 +08:00
    @dog82
    @dif
    因为业务需要重构
    Valid
        30
    Valid  
       2023-09-14 17:18:36 +08:00
    自由代码,没有任何约束
    CodeGou
        31
    CodeGou  
       2023-09-14 17:28:05 +08:00
    前辈不写出还能跑的屎山,哪来的后代能换钱的工作内容。这是大树好乘凉啊~
    EEEEx
        32
    EEEEx  
       2023-09-14 17:36:33 +08:00
    能跑的代码就是好代码
    yyysuo
        33
    yyysuo  
       2023-09-14 17:45:11 +08:00
    屎山真的不是问题,重构大概率出 bug ,才是大问题。
    TArysiyehua
        34
    TArysiyehua  
       2023-09-14 17:46:34 +08:00
    你主管有不懂技术,自己包装一下就说是重构了呀?这么老实,工资一定涨得很慢吧。(阴险脸)
    SeanTheSheep
        35
    SeanTheSheep  
       2023-09-14 17:48:05 +08:00 via Android
    我装了一个周的 vb6, 我放弃了,直接写个新的拉倒
    clino
        36
    clino  
       2023-09-14 17:48:06 +08:00
    正在重构重写多年以前的 perl 代码,还好现在有 AI 辅助,读和写代码的效率高很多,否则 t*d 要憋屈死
    yishuiliunian
        37
    yishuiliunian  
       2023-09-14 18:00:48 +08:00   ❤️ 1
    只要人和代码有一个能跑就行
    lakehylia
        38
    lakehylia  
       2023-09-14 18:25:51 +08:00
    只要算 KPI 那就重构呗,拿钱办事没毛病
    Justin13
        39
    Justin13  
       2023-09-14 18:29:05 +08:00 via Android
    还行吧,我现在在给 ios 的项目的一个核心部分加功能
    大部分代码至少都有 10 年的,说至少是因为当初迁移到 git 就是 10 年前
    里面充斥着各种重复,错误,无用,特殊的代码
    而我是一个写 js 的前端,之前没有接触过任何苹果相关技术
    现在每天大概三分之一时间在看代码和逻辑,三分之一学习语言和 UI 库,剩下的时间在骂娘。。
    至于原来维护的人呢?写前端去了。。
    zhuangzhuang1988
        40
    zhuangzhuang1988  
       2023-09-14 19:02:03 +08:00
    用 Pyqt 后会更加屎了
    uCharles
        41
    uCharles  
       2023-09-14 19:27:30 +08:00
    作为菜鸟,高内聚,低耦合是啥意思呢?有通俗的解释不
    ITdream
        42
    ITdream  
       2023-09-14 19:34:05 +08:00
    ITdream
        43
    ITdream  
       2023-09-14 19:34:19 +08:00
    @uCharles
    "高内聚" 和 "低耦合" 是软件设计中的两个重要原则,用于评估和指导软件架构和模块化设计。

    高内聚 (High Cohesion):
    高内聚指的是模块或组件内部元素(例如函数、方法、类等)之间的联系和关联度。
    具有高内聚的模块意味着模块内的元素都紧密相关,执行相似的任务或具有相同的责任。
    高内聚有助于提高代码的可维护性、可重用性和可测试性,因为相关功能都放在一个地方。
    示例:一个处理订单的模块应该包含处理订单、验证订单、计算总价等相关功能,而不是将这些功能分散在不同的模块中。

    低耦合 (Low Coupling):
    低耦合指的是模块或组件之间的相互依赖程度。
    具有低耦合的模块之间的依赖性较少,它们应该能够独立地进行开发、测试和维护。
    低耦合有助于提高系统的灵活性和可扩展性,因为更改一个模块不太可能影响其他模块。
    示例:一个订单模块应该尽可能少地依赖于其他模块,如用户管理模块、支付模块等。

    综合来说,高内聚和低耦合是追求良好的软件设计和架构的目标。通过将相关功能组织在一起(高内聚)并减少模块之间的依赖性(低耦合),可以创建更易于维护、扩展和理解的软件系统。这些原则有助于减少潜在的错误和提高代码的质量。
    996bujiaban
        44
    996bujiaban  
       2023-09-14 19:47:35 +08:00
    冲动啊,十年前的也重构
    ldyisbest
        45
    ldyisbest  
       2023-09-14 21:14:16 +08:00
    公司项目里面有一个 2000 行代码的方法,还有一个 4000 行方法的代码。json 、map 到处飞。
    ldyisbest
        46
    ldyisbest  
       2023-09-14 21:15:15 +08:00
    公司项目里面有一个 2000 行代码的方法,还有一个 4000 行代码的方法。json 、map 到处飞。能跑就行
    bequt
        47
    bequt  
       2023-09-14 21:49:54 +08:00
    感觉到 品味屎山 的感觉
    winterbells
        48
    winterbells  
       2023-09-14 22:01:34 +08:00 via Android
    我已经放弃了
    耗费近一个月才将 50%的数据库代码独立出来
    剩下的部分改过七八版了,每次都牵扯点别的地方代码导致没心情动了

    base 里面还去一个个判断子类型,真是服了。项目里全 tm 相互引用的,真正的牵一发而动全身。

    现在唯一能做的就是保证新页面的独立性,哪怕一个页面屎山了也无所谓,至少不影响别的地方重构

    还有我发现,很多人都从来不格式化代码的,明明 IDEA 系可以勾选提交时格式化
    eatgrass
        49
    eatgrass  
       2023-09-14 22:17:03 +08:00
    @shangwuli 定期评审是一种很糟糕的做法
    forgottencoast
        50
    forgottencoast  
       2023-09-14 22:58:32 +08:00
    @sundev #2
    这种直接重构就是在加油站玩火。
    最好是切割重构,除了改 bug ,所有的改动都要在新的代码上实现,最后做一个访问记录,发现多长时间没人访问了就关了。
    GeruzoniAnsasu
        51
    GeruzoniAnsasu  
       2023-09-14 23:11:41 +08:00
    嵌入式落后业界 20 年不是瞎说的
    fdwjtz
        52
    fdwjtz  
       2023-09-14 23:33:20 +08:00
    @clino perl 真是要老命,难写的一批
    tuomasi
        53
    tuomasi  
       2023-09-14 23:48:19 +08:00
    你这才几千行代码,哪叫屎山,顶多屎橛
    sundev
        54
    sundev  
       2023-09-15 00:11:54 +08:00
    @forgottencoast 都是没办法,整个公司的核心功能都在上面,重写的代价也非常高,况且这么长时间,要了解当时的需求也不可能了,如果要照着代码一行行翻译也不可能!
    Jaosn
        55
    Jaosn  
       2023-09-15 01:13:31 +08:00
    感谢微服务,真的幸福很多
    zpxshl
        56
    zpxshl  
       2023-09-15 01:58:00 +08:00 via Android
    一个 fragment 一万行代码
    kkk9
        57
    kkk9  
       2023-09-15 02:04:21 +08:00   ❤️ 2
    每一行代码都有它特别的作用,不要怀疑前辈们的代码水平,要多想想这么多年了,有没有涨工资,有没有认真工作。。。。
    enchilada2020
        58
    enchilada2020  
       2023-09-15 07:29:37 +08:00 via Android
    哈哈哈哈哈哈哈哈哈同是天涯铲屎人
    genicsoft123
        59
    genicsoft123  
       2023-09-15 08:10:43 +08:00
    哈哈哈爆炸。。。。
    zhsso
        60
    zhsso  
       2023-09-15 08:37:18 +08:00 via Android
    有没有一种可能
    有其他线程也在调用 scanThreadData->mcuFirmWare_path ,然后调 ScanFirewareBin(IS_NGFDFILE, ProductCodeStr)期间,这个线程有一定几率因为用了错误的 mcuFirmWare_path ,导致出错。然后某代💩山维护者发现,诶,先清空 mcu 固件路径好像就解决了
    villivateur
        61
    villivateur  
    OP
       2023-09-15 08:42:02 +08:00
    @zhsso 没有可能,我看了,就在这用
    dream4ever
        62
    dream4ever  
       2023-09-15 08:47:05 +08:00
    听说我,谢谢你,因为有你,今天很开心
    zhsso
        63
    zhsso  
       2023-09-15 08:47:18 +08:00 via Android
    @villivateur 那还好,最多多了一行无效代码,至少不是因为其他莫名其妙的原因😂
    locoz
        64
    locoz  
       2023-09-15 08:57:50 +08:00 via Android
    @codeself #1 AI 都不一定看得懂屎山…太多屎的屎山还是得要人工描述指引,要不然写出来的还是会带屎
    UIXX
        65
    UIXX  
       2023-09-15 09:17:58 +08:00   ❤️ 2
    别说了,看到 w 大写已经浑身难受...
    hokori
        66
    hokori  
       2023-09-15 09:31:53 +08:00
    诶 我也在一个类似的 qt 项目 和你说的一样的感觉 但是我选择不动,继续堆料. 不敢重构.
    villivateur
        67
    villivateur  
    OP
       2023-09-15 09:32:28 +08:00
    @UIXX 那是你没注意到 ScanFirewareBin 还拼错了,哈哈
    shunia
        68
    shunia  
       2023-09-15 09:39:55 +08:00
    领导花了不少钱找了一个外包团队花两年时间做了一坨实际功能只包含一个页面、代码量不超过 5000 行的屎山,并且 bug 多多,性能也不满足需求。
    然后我刚花一个月重写了这些不懂基础原理(辣鸡老框架)也不知道业务逻辑(从产品到代码基本 0 文档)的功能,谁知这几天开会说这些都没用了,重新做一套别的,目前的东西几乎不可复用。

    你才三四天就崩溃了?工作还得继续,活儿还得继续接不是。
    zzz2021zzz
        69
    zzz2021zzz  
       2023-09-15 09:40:38 +08:00
    @zjj19950716 #12 哈哈,真知灼见
    nenseso
        70
    nenseso  
       2023-09-15 09:43:49 +08:00
    是时候展示一波屎上雕花的技术了
    justfindu
        71
    justfindu  
       2023-09-15 09:46:05 +08:00
    我看我三年前写的项目也是一样的屎山, 但是我真的不想改 哈哈哈哈
    Chad0000
        72
    Chad0000  
       2023-09-15 09:49:16 +08:00
    @ITdream #43
    说到低耦合:我大胆地设计了一套框架,命名为独立服务/模块,正在公司内部开展。即每个服务和模块都是独立的,完全不依赖于其他服务和模块(当然基础设施层还是要依赖的)。像你举的那个例子,在我的设计里连订单卖什么东西都不是由订单负责的了。

    想看看这种设计最终会不会成功,哈哈。
    hankai17
        73
    hankai17  
       2023-09-15 09:59:28 +08:00
    我记得 QT 框架 有莫名的 BUG
    要规避这些 BUG 可能代码写的就很奇怪
    不知道是不是这个原因
    nevermoreluo
        74
    nevermoreluo  
       2023-09-15 10:08:54 +08:00
    也在重构说是,还是自己提议的,不过侥幸的是主业务逻辑十分单一。
    我只重构主业务逻辑并保证主业务,其他的拆分出模块来,尽量不改函数里面的逻辑(是的之前有一个全局单例,好几个线程,很多个功能全部挂在这个单例上),确保下次有人再改,只用对某一部分进行修改或者重构。

    剩下的除非真的是 bug ,否则我就告诉他们,好多年了,That's a feature 。

    害 我感觉一次不要面对太多,解决主要矛盾先
    9i5NngJHI4P7dm42
        75
    9i5NngJHI4P7dm42  
       2023-09-15 10:13:13 +08:00
    "不乏长度为 9 的数组访问第 9 个变量这种奇葩事"

    这是什么意思, 没有理解
    xzyDeathGun
        76
    xzyDeathGun  
       2023-09-15 10:56:53 +08:00
    @odifjg9384hg 数组长度为 9,最大索引是 8,估计说的是索引为 9 的元素吧, 数组越界了
    uCharles
        77
    uCharles  
       2023-09-15 10:59:37 +08:00
    @ITdream 感谢答疑
    macha
        78
    macha  
       2023-09-15 11:19:39 +08:00
    至少楼主贴出来的这 2 行代码没啥大毛病。
    其他看文字描述的代码好像问题比较大。
    1055619878
        79
    1055619878  
       2023-09-15 11:25:37 +08:00
    敢重构屎山不是勇士就是大神
    lightjiao
        80
    lightjiao  
       2023-09-15 11:27:54 +08:00 via iPhone
    不如用 C# 重写
    Kenmin
        81
    Kenmin  
       2023-09-15 11:34:14 +08:00   ❤️ 1
    我现在是重构屎山的第三个礼拜
    理顺需求后发现原有代码五成以上是废弃物,不如按照需求重写
    问题在于得先理顺需求……
    unco020511
        82
    unco020511  
       2023-09-15 11:39:19 +08:00
    我只能说重构要谨慎
    darkengine
        83
    darkengine  
       2023-09-15 11:49:18 +08:00
    这个项目不适合重构,适合重写,根据需求重新用 PyQt 开发,还不用看原来的屎山代码。
    opentrade
        84
    opentrade  
       2023-09-15 11:55:07 +08:00
    多么完美的注释
    moyupoi10
        85
    moyupoi10  
       2023-09-15 12:01:10 +08:00
    我们公司也是,之前刚入职的时候给我丢了 5 个屎山项目,有的项目一页 1 万多行代码,函数重复、命名名称相同并大小写不同,项目有的 5~6 年,有的 1~3 年,让我一周内重构,当时脑子就翁一下,仿佛觉得我一周可以完成别人团队 5 年完成的项目
    franswish
        86
    franswish  
       2023-09-15 12:03:42 +08:00 via Android   ❤️ 1
    领导分配工时,让你重构还不好啊(前提是工时合理)
    领导说,就在屎山上继续开发不是更崩溃
    bclerdx
        87
    bclerdx  
       2023-09-15 12:15:18 +08:00
    @moyupoi10 让你一周完成,因为你是大拿。
    NutChocHoney
        88
    NutChocHoney  
       2023-09-15 13:26:16 +08:00
    既然领导知道是屎山,重构有难度,就直接把问题抛出来,多分几个人一起做,别自己闷头干啊
    bzsh
        89
    bzsh  
       2023-09-15 14:16:07 +08:00
    @sundev 这不是屎山,这是金山,这是饭碗的加固器
    xieren58
        90
    xieren58  
       2023-09-15 14:21:37 +08:00
    拿钱办事...
    kkk9
        91
    kkk9  
       2023-09-15 14:32:25 +08:00
    @bzsh #89 饭碗加固器?那必然是另一座屎山。
    debuggeeker
        92
    debuggeeker  
       2023-09-15 15:53:15 +08:00
    这有啥,证明你心态不行,我已经内心毫无波动
    nebulabox
        93
    nebulabox  
       2023-09-15 16:30:09 +08:00   ❤️ 2
    自以为是的人很多,总觉得自己的代码能比别人写的好,瞎几把折腾,最后一点用没有,还导致很多 bug 。

    比如你说的例子,你如果第一行的清空去掉,多线程环境完全可能出现直接 core dump 。因为后续的 ScanFirewareBin 执行可能在在另一个线程,里面代码很有可能还会访问 mcuFirmWare_path 的值,结果就上了以前的垃圾数值。即使不是多线程,也可能出错。

    还有各种可能你根本无法预知。也可能那个前任只是随手写了一行没用的代码,但是没副作用,但是你就不应该瞎几把改。
    yxzblue
        94
    yxzblue  
       2023-09-15 17:17:32 +08:00
    还有各种可能你根本无法预知。也可能那个前任只是随手写了一行没用的代码,但是没副作用,但是你就不应该瞎几把改。

    ---
    可能也不是没用的代码,写的时候有他的原因,就是三个月之后 问他,他也不记得了。然后少了那行代码,特殊情况就会出问题。为什么会在某个情况出问题,那还不是前前前任留下的屎山导致的咯
    dwzfuck
        95
    dwzfuck  
       2023-09-15 17:30:27 +08:00
    韩信带净化, 能跑就行, 千万别做铲屎人。
    flyqie
        96
    flyqie  
       2023-09-15 17:41:28 +08:00 via Android
    @dwzfuck #95

    前面老哥说得好,要么人能跑要么代码能跑。
    kongkong23
        97
    kongkong23  
       2023-09-15 17:41:52 +08:00
    没有 KPI ,不重构能跑和重构后能跑,是一件事;
    如果真的不能跑了,那又是另一件事;

    有 KPI ,不重构能跑和重构后能不能跑,是两件事;
    jinsongzhao
        98
    jinsongzhao  
       2023-09-15 18:13:05 +08:00
    我就经常重构,甚至重写,乐在其中,不过基本都是自己的,别人的少。
    HowToMakeLove
        99
    HowToMakeLove  
       2023-09-15 18:16:54 +08:00
    先画图吧
    easteast123
        100
    easteast123  
       2023-09-15 20:48:49 +08:00
    以前听过合作方做财务软件,他们的代码用了 6 种语言,都是一茬一茬的人在给自己做试验
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2690 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 12:21 · PVG 20:21 · LAX 05:21 · JFK 08:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.