因为 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 那段是怎么个逻辑
还好经过我的不懈努力,程序能正常工作了,上面想的几个功能也都实现了。从下午两点一直搞到晚上八点,晚饭也烦的没有吃,一个下午全耗在这了,啥正事也没干,就为了这个小功能(责任全在微信)。为什么说是挫败感呢?因为我感觉这个真是个挺简单的程序,而且晚上写完回看确实感觉很简单,但是耗费了我这么长的时间,而且感觉自己好菜....我不是科班出身,写代码全是个人爱好,我一直认为自己有点写代码的天赋,现在看来我应该去重新系统的学习一下如何写代码。
晚上睡不着,写出来感觉舒服多了,晚安兄弟们
1
Aloento 2022-09-24 01:15:40 +08:00 1
加油加油,我写代码推翻重来的次数可多了,根本不担心的
|
2
kkeep 2022-09-24 01:27:20 +08:00 via Android 1
想想
|
3
agagega 2022-09-24 01:49:24 +08:00 via iPhone 1
挺正常的,不要太在意,科班出身的人代码如果写得不多也容易这样。把思路转换成代码是一种需要训练的能力,所谓 LeetCode 考的并不只是对算法 /数据结构的理解,更重要的就是这个把思路转换成代码的能力
|
4
levelworm 2022-09-24 07:03:22 +08:00 via Android 1
我觉得得先设计清楚了再写,就能一次成功了。
|
5
swulling 2022-09-24 07:09:58 +08:00 1
工程经验问题,不要写嵌套层级超过 3 的 if
|
6
wzzzx 2022-09-24 09:18:19 +08:00 3
这里最最最主要的问题是 “写着写着我开始不断想着添加新功能”
|
7
winglight2016 2022-09-24 09:36:43 +08:00 1
套了三层 for 循环不提,这么多 ifelse ,都没想过画个流程图吗?
|
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: ... |
9
Kiriya 2022-09-24 11:31:38 +08:00 1
你写代码解析一堆屎山=你写了屎山代码🐶
|
10
ma836323493 2022-09-24 11:34:35 +08:00 1
三层 for 循环 , 里面的 for 循环改成 函数, 特殊的 if 条件写在前面
|
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) 最后把伪代码里没实现的函数实现了就行。 |
12
acehinnnqru 2022-09-24 17:38:40 +08:00 via iPhone 1
先确定思路和架构挺好的,返回来看的时候也没那么挫败
|
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{ ... } } } } |
14
heavymetals OP @THESDZ
@acehinnnqru @msg7086 @ma836323493 @ilcn @swulling @agagega @Aloento @levelworm 谢谢老哥们的悉心指导,感觉又学到了很多东西 |
15
christin 2022-09-24 21:14:30 +08:00 via iPhone 1
哈哈 比我这个科班出身的好多啦,我可能想想功能麻烦就不想做了。
|