今天发生了件挫败感很强的事 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dcvsiug
V2EX    随想

今天发生了件挫败感很强的事

  •  
  •   dcvsiug 2022-09-24 01:13:05 +08:00 3569 次点击
    这是一个创建于 1117 天前的主题,其中的信息可能已经有所发展或是发生改变。

    因为 MacOs 端微信保存文件的路径是这种形式

    /Message/MessageTemp/一堆随机字符 /File(OpenData)/2022-09

    相对于 Win 端的File/2022-09 太过复杂,而且每个联系人的随机字符串都不同,查找起来不太方便,所以今天(2022 年 9 月 23 日)中午的时候我打算写一个能定期将微信文件备份到特定文件夹,并按月份归档的 python 小程序。

    刚开始我觉着很简单,不就是读取创建时间然后复制粘贴吗,然后我就开始了愉快地面向谷歌编程。

    写着写着我开始不断想着添加新功能,微信每收发一个文件不管文件是否一样,都会在本地保存一份 --> 所以想着根据文件名去重 --> 又想到可能会有不同内容的同名文件 --> 不如根据 MD5+文件名去重 -- > 全查 MD5 太慢 --> 先看名字再检查 MD5

    然后我自己就乱了,前面写了一大堆 if else break ,也没怎么写注释,出错以后往上查自己也看不懂了......

    当时真是气死我了

    大概就是这样:

    for path, dir_list, source_file_list in g: for source_file_list in source_file_list: riqi = get_change_time(str(path) + '/' + str(source_file_list)) target_path = '' + riqi target_path_file_name = return_target_file_name(target_path) for i in target_path_file_name: if i == source_file_list: md5_target = return_md5(target_path + '/' + i) md5_source = return_md5(path + '/' + source_file_list) if md5_target==md5_source: status=2 break else: print(i) target_path_file_name.remove(i) for uu in target_path_file_name: md5_target = return_md5(target_path + '/' + uu) md5_source = return_md5(path + '/' + source_file_list) if uu == target_path_file_name: status=1 break else: status=2 break else: status=3 

    现在我也没理清楚计算 md5 那段是怎么个逻辑

    还好经过我的不懈努力,程序能正常工作了,上面想的几个功能也都实现了。从下午两点一直搞到晚上八点,晚饭也烦的没有吃,一个下午全耗在这了,啥正事也没干,就为了这个小功能(责任全在微信)。为什么说是挫败感呢?因为我感觉这个真是个挺简单的程序,而且晚上写完回看确实感觉很简单,但是耗费了我这么长的时间,而且感觉自己好菜....我不是科班出身,写代码全是个人爱好,我一直认为自己有点写代码的天赋,现在看来我应该去重新系统的学习一下如何写代码。

    晚上睡不着,写出来感觉舒服多了,晚安兄弟们

    15 条回复    2022-09-24 21:14:30 +08:00
    Aloento
        1
    Aloento  
       2022-09-24 01:15:40 +08:00   1
    加油加油,我写代码推翻重来的次数可多了,根本不担心的
    kkeep
        2
    kkeep  
       2022-09-24 01:27:20 +08:00 via Android   1
    想想
    agagega
        3
    agagega  
       2022-09-24 01:49:24 +08:00 via iPhone   1
    挺正常的,不要太在意,科班出身的人代码如果写得不多也容易这样。把思路转换成代码是一种需要训练的能力,所谓 LeetCode 考的并不只是对算法 /数据结构的理解,更重要的就是这个把思路转换成代码的能力
    levelworm
        4
    levelworm  
       2022-09-24 07:03:22 +08:00 via Android   1
    我觉得得先设计清楚了再写,就能一次成功了。
    swulling
        5
    swulling  
       2022-09-24 07:09:58 +08:00   1
    工程经验问题,不要写嵌套层级超过 3 的 if
    wzzzx
        6
    wzzzx  
       2022-09-24 09:18:19 +08:00   3
    这里最最最主要的问题是 “写着写着我开始不断想着添加新功能”
    winglight2016
        7
    winglight2016  
       2022-09-24 09:36:43 +08:00   1
    套了三层 for 循环不提,这么多 ifelse ,都没想过画个流程图吗?
    ilcn
        8
    ilcn  
       2022-09-24 09:42:52 +08:00   1
    教你个简单易行的办法。用 IDE ,比如我用 jetbrains ,每写一个 if condition 就用 Ctrl+Alt+M 换成一个易理解的名字。

    比如:
    if line_number_is_1:
    if column_count_is_5:
    ...
    Kiriya
        9
    Kiriya  
       2022-09-24 11:31:38 +08:00   1
    你写代码解析一堆屎山=你写了屎山代码
    ma836323493
        10
    ma836323493  
       2022-09-24 11:34:35 +08:00   1
    三层 for 循环 , 里面的 for 循环改成 函数, 特殊的 if 条件写在前面
    msg7086
        11
    msg7086  
       2022-09-24 12:06:19 +08:00   1
    这种一大段 for 循环嵌套的写法挺不好的。
    写代码要先分割功能,把一个大功能分割成多个小功能的组合,分而治之。
    比如你这里至少会有( 1 )在目录下遍历文件列表( 2 )对比源和目标文件列表找出新增的文件( 3 )对比相同文件的 hash ( 4 )备份文件。那你分别实现这 4 个功能,再组合起来就好了。

    用伪代码来说就是:
    src_file_list = 某函数
    dst_file_list = 某函数
    new_file_list = src 中不在 dst 的文件集合
    common_file_list = src 与 dst 的交集
    changed_common_file_list = 交集里 MD5 不相同的文件集合
    backup(new_file_list)
    backup(changed_common_file_list)

    最后把伪代码里没实现的函数实现了就行。
    acehinnnqru
        12
    acehinnnqru  
       2022-09-24 17:38:40 +08:00 via iPhone   1
    先确定思路和架构挺好的,返回来看的时候也没那么挫败
    THESDZ
        13
    THESDZ  
       2022-09-24 20:04:33 +08:00   1
    仅从你的描述来看:
    虽然确定思路和架构,但是好像没有封装.
    那就导致了,你虽然设计了层次,但是从你的实现中看不出层次,而阅读代码的人(不管是你还是其他人)是不可能看设计的去推导代码的.

    我一般这么做:
    设计好思路,然后抽象出接口(或者方法),哪些做为主干,哪些作为分支.
    主干中的状态如何传递,是走上下文还是传入传出?
    枝干部分如何调用(写个代理类统一触发,还是作为回调外部传入)?

    写好每一个变量名,每一个方法名,减少非代码注释(避免后续注释没有随着代码变更导致更加难以理解)

    实现的代码条理清晰: 主干很简练,一上来就能读懂在干嘛,子模块通过方法名就可以猜测出在干嘛.
    拓展性也不错: 封装后只需要改封装部分,枝干部分直接增加回调或代理类中修改.


    举个例子,根据 op 的描述:
    主干部分为:
    1.读取微信的文件列表
    2.判断哪些要备份
    3.判断重复
    4.备份

    那就 main

    var cOntext= make(map[string]interface{})
    func BackupWechatFile(rootPath,backPath string){
    files ,err := getFilesByRootpath(rootPath)
    if err!=nil {
    ...
    }
    for _,file := range files{
    isRepeated := judgeFileIfRepeated(file)
    if !isRepeated {
    err := backUp(file)
    if err!=nil{
    ...
    }
    }
    }
    }
    dcvsiug
        14
    dcvsiug  
    OP
       2022-09-24 20:54:59 +08:00   1
    @THESDZ
    @acehinnnqru
    @msg7086
    @ma836323493
    @ilcn
    @swulling
    @agagega
    @Aloento
    @levelworm
    谢谢老哥们的悉心指导,感觉又学到了很多东西
    christin
        15
    christin  
       2022-09-24 21:14:30 +08:00 via iPhone   1
    哈哈 比我这个科班出身的好多啦,我可能想想功能麻烦就不想做了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     926 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 20:50 PVG 04:50 LAX 13:50 JFK 16:50
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86