规范与标准
版本管理
强制要求在项目中使用 git
进行代码版本控制和管理,以杜绝使用花式后缀副本文件版本管理法!
git简单入门
推荐观看下面这两个视频:
git可视化工具
Important
vscode的Git Graph扩展(免费)。
上面视频中用到的软件,
GitKraken Legendary Git Tools | GitKraken
虽然是英文没有简中界面,但可视化做的不错。相应的vscode扩展是GitLens,大部分功能免费,部分功能付费。
git基本操作(必须)
- 初始化仓库(命令和vscode两种方式)。
-
git add
和git commit
操作(命令和vscode两种方式)。 - 使用vscode查看git可视化树状图,并查看文件的修改记录。
-
git clone
远程仓库。
git常规操作
- 更改git中上一个commit(命令和vscode两种方式)。
- 编写
.gitignore
忽略指定文件和路径。 - 在命令行中设置(添加、删除、修改、查看)git的远程仓库地址。
- 推送代码到远程仓库(命令和vscode两种方式)。
- 用vscode将远程仓库中的更新同步到本地仓库。
- 在指定commit上创建分支(命令和vscode两种方式)。
- 切换分支(命令和vscode两种方式)。
- 删除指定本地分支(vscode git graph上可视化操作很方便,命令虽不难但容易忘记/记混)。
- 用vscode合并无冲突的分支。
git进阶操作
- 用vscode合并分支并处理冲突。
- 用命令移动文件。(1)
- 用命令删除文件。(2)
- 用命令撤销最后一个commit并保留更改。(3)
- 用命令添加submodule到指定路径下。(4)
- clone仓库时连同submodule一起clone。(5)
- 用命令checkout指定commit的指定文件(不会改变HEAD)。(6)
- 用vscode checkout指定commit(会改变HEAD)。
git mv <old_path> <new_path>
git rm <path>
git reset HEAD^
git submodule add <url> [<path>]
git clone --recurse-submodules <url>
git checkout <commit> <path>
为什么要使用Git
想象一下你正在玩Flappy Bird, 你今晚的目标是拿到100分, 不然就不睡觉. 经过千辛万苦, 你拿到了99分, 就要看到成功的曙光的时候, 你竟然失手了! 你悲痛欲绝, 滴血的心在呼喊着, "为什么上天要这样折磨我? 为什么不让我存档?"
想象一下你正在写代码, 你今晚的目标是实现某一个新功能, 不然就不睡觉. 经过千辛万苦, 你终于把代码写好了, 保存并编译运行, 你看到调试信息一行一行地在终端上输出. 就要看到成功的曙光的时候, 竟然发生了段错误! 你仔细思考, 发现你之前的构思有着致命的错误, 但之前正确运行的代码已经永远离你而去了. 你悲痛欲绝, 滴血的心在呼喊着, "为什么上天要这样折磨我?" 你绝望地倒在屏幕前... 这时, 你发现身边渐渐出现无数的光玉, 把你包围起来, 耀眼的光芒令你无法睁开眼睛... 等到你回过神来, 你发现屏幕上正是那份之前正确运行的代码! 但在你的记忆中, 你确实经历过那悲痛欲绝的时刻... 这一切真是不可思议啊...
人生如戏, 戏如人生
人生就像不能重玩的Flappy Bird, 但软件工程领域却并非如此, 而那不可思议的光玉就是"版本控制系统". 版本控制系统给你的开发流程提供了比朋也收集的更强大的光玉, 能够让你在过去和未来中随意穿梭, 避免上文中的悲剧降临你的身上.
没听说过版本控制系统就完成实验, 艰辛地排除万难, 就像游戏通关之后才知道原来游戏可以存档一样, 其实玩游戏的时候进行存档并不是什么丢人的事情.
在实验中, 我们使用 git
进行版本控制. 下面简单介绍如何使用 git
.
游戏设置
...
查看存档信息
...
存档
你可以像以前一样编写代码. 等到你的开发取得了一些阶段性成果, 你应该马上进行"存档".
...
读档
如果你遇到了上文提到的让你悲痛欲绝的情况, 现在你可以使用光玉来救你一命了. 首先使用 git log
来查看已有的存档, 并决定你需要回到哪个过去. 每一份存档都有一个hash code, 例如 b87c512d10348fd8f1e32ddea8ec95f87215aaa5
, 你需要通过hash code来告诉 git
你希望读哪一个档. 使用以下命令进行读档...
第三视点
...
不同的分支之间不会相互干扰, 这也给项目的分布式开发带来了便利. 有了分支功能, 你就可以像第三视点那样在一个世界的不同时间(一个分支的多个存档), 或者是多个平行世界(多个分支)之间来回穿梭了.
...
为什么要使用.gitignore
...
上面提到了 .gitignore
可以让 Git 忽略目录中某些文件, 且不让它们出现在 Git 仓库中. 这有什么用呢?
你在开发过程中难免会产生一些 “只对你自己有用” 且 “不值得永久保留” 的东西. 比如你在开发的过程中希望写几个简单的输入来测试你的程序, 或者验证你程序里的某处是否写对了, 于是你新建了个名字叫 test.txt
的文件, 里面写了一些测试的内容, 然后你在本地调试的时候会让你的程序读取这个文件.
test.txt
显然只是个用来存放写一些只对你自己有用的临时内容的文件, 你不希望让 Git 每次都记录这个文件的更改 (因为没意义), 所以你可以把它写进 .gitignore
中, 来让 Git 忽略它.
其他类似的情况还包括, 你使用 VS Code 或 IDEA 开发你的编译器, 这些代码编辑器/IDE 可能会在项目中生成一些配置文件 (.vscode
或 .idea
), 这些文件通常也是不需要被 Git 记录的, 因为其中包含了你的一些个人配置.
...
代码规范
具体的示例可以参考仓库中的各个视觉的代码仓库,各个仓库在编写代码时都已经将可读性考虑在内。
关于变量名和函数名
变量名和函数名应该要能较为直观地表达出其所代表的含义或功能。从个人过往经验来看,在阅读代码时,代码中最容易关注到和试图去理解的就是变量名和函数名(比如在查看别人封装好的函数的具体实现的内部代码时)和简单的代码结构,因此,即使没有注释说明,清晰的变量名和函数名也能很快让人理解代码的功能和作用。
越是重要和关键的变量和函数,命名越要清晰直观,而临时的一些变量可以使用简短的命名(如用于循环的变量,i
←index
,img
←image
,anno
←annotation
)。
此外,可以使用稍长一些的命名,来代替短命名加注释的说明代码的方式。如 ultralytics_results_to_detected_objects()
,与使用 get_detected_objects()
加注释说明的方式相比,前者在看到函数名时就能大致知道这个函数的功能,而后者则需要查看函数定义处的注释才能知道这个函数的功能。但最长不要超过6-7个单词,太长可能会使得在显示屏中一行显示不下,导致需要换行,影响可读性。如果6个单词还不能把函数的功能表达清楚,说明这个函数的功能已经过于复杂,应该将其拆分成几个小函数。
另外,此处给出一些通用的不同情形下的命名方法和示例:
情形 | 命名方法 | 示例 |
---|---|---|
一般变量和函数 | 蛇形命名法 单词全小写并用下划线 _ 连接 |
annotated_frame |
类名 | 驼峰命名法 单词首字母大写其余小写 |
PostureIdentifier |
常量(一般位于python文件开头,导入各模块之后) | 单词全大写并用下划线_ 连接 |
CURRENT_DIR |
关于注释
个人理解中,注释最有用的地方在于,在一段较长的代码段中,添加空行之后直观的观感上还是很长时,此时添加注释打断这样“长”的观感,让人更容易把代码分成几段来阅读和理解(至少在python中是这样)。
如果把代码类比成文本:
代码 文本 空行 逗号 ,
注释 句号 。
函数 段落
Example
其次就是对于一些关键的参数及其设置进行一些简要的说明。
关于docstring
在IDE中编写代码时,docstring可以使函数和类在调用时,能够在鼠标悬停时显示出来,说明函数和类的功能,以及各个参数的作用等。因此建议在函数和类编写基本完成后,添加docstring(可以自己手动编写或者借助copilot)。